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
56 namespace vkt
57 {
58 namespace BindingModel
59 {
60 namespace
61 {
62
63 enum ResourceFlag
64 {
65 RESOURCE_FLAG_IMMUTABLE_SAMPLER = (1u << 0u),
66
67 RESOURCE_FLAG_LAST = (1u << 1u)
68 };
69
70 static const char* const s_quadrantGenVertexPosSource = " highp int quadPhase = gl_VertexIndex % 6;\n"
71 " highp int quadXcoord = int(quadPhase == 1 || quadPhase == 4 || quadPhase == 5);\n"
72 " highp int quadYcoord = int(quadPhase == 2 || quadPhase == 3 || quadPhase == 5);\n"
73 " highp int quadOriginX = (gl_VertexIndex / 6) % 2;\n"
74 " highp int quadOriginY = (gl_VertexIndex / 6) / 2;\n"
75 " quadrant_id = gl_VertexIndex / 6;\n"
76 " result_position = vec4(float(quadOriginX + quadXcoord - 1), float(quadOriginY + quadYcoord - 1), 0.0, 1.0);\n";
77
isUniformDescriptorType(vk::VkDescriptorType type)78 bool isUniformDescriptorType (vk::VkDescriptorType type)
79 {
80 return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
81 type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
82 type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
83 }
84
isDynamicDescriptorType(vk::VkDescriptorType type)85 bool isDynamicDescriptorType (vk::VkDescriptorType type)
86 {
87 return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || type == vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
88 }
89
verifyDriverSupport(const vk::VkPhysicalDeviceFeatures & deviceFeatures,vk::VkDescriptorType descType,vk::VkShaderStageFlags activeStages)90 void verifyDriverSupport(const vk::VkPhysicalDeviceFeatures& deviceFeatures,
91 vk::VkDescriptorType descType,
92 vk::VkShaderStageFlags activeStages)
93 {
94 switch (descType)
95 {
96 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
97 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
98 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
99 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
100 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
101 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
102 // These are supported in all stages
103 return;
104
105 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
106 case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
107 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
108 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
109 if (activeStages & (vk::VK_SHADER_STAGE_VERTEX_BIT |
110 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
111 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT |
112 vk::VK_SHADER_STAGE_GEOMETRY_BIT))
113 {
114 if (!deviceFeatures.vertexPipelineStoresAndAtomics)
115 TCU_THROW(NotSupportedError, (de::toString(descType) + " is not supported in the vertex pipeline").c_str());
116 }
117
118 if (activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT)
119 {
120 if (!deviceFeatures.fragmentStoresAndAtomics)
121 TCU_THROW(NotSupportedError, (de::toString(descType) + " is not supported in fragment shaders").c_str());
122 }
123 return;
124
125 default:
126 DE_FATAL("Impossible");
127 }
128 }
129
viewTypeToImageType(vk::VkImageViewType type)130 vk::VkImageType viewTypeToImageType (vk::VkImageViewType type)
131 {
132 switch (type)
133 {
134 case vk::VK_IMAGE_VIEW_TYPE_1D:
135 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY: return vk::VK_IMAGE_TYPE_1D;
136 case vk::VK_IMAGE_VIEW_TYPE_2D:
137 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY: return vk::VK_IMAGE_TYPE_2D;
138 case vk::VK_IMAGE_VIEW_TYPE_3D: return vk::VK_IMAGE_TYPE_3D;
139 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
140 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return vk::VK_IMAGE_TYPE_2D;
141
142 default:
143 DE_FATAL("Impossible");
144 return (vk::VkImageType)0;
145 }
146 }
147
getImageLayoutForDescriptorType(vk::VkDescriptorType descType)148 vk::VkImageLayout getImageLayoutForDescriptorType (vk::VkDescriptorType descType)
149 {
150 if (descType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
151 return vk::VK_IMAGE_LAYOUT_GENERAL;
152 else
153 return vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
154 }
155
getTextureLevelPyramidDataSize(const tcu::TextureLevelPyramid & srcImage)156 deUint32 getTextureLevelPyramidDataSize (const tcu::TextureLevelPyramid& srcImage)
157 {
158 deUint32 dataSize = 0;
159 for (int level = 0; level < srcImage.getNumLevels(); ++level)
160 {
161 const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
162
163 // tightly packed
164 DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
165
166 dataSize += srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
167 }
168 return dataSize;
169 }
170
writeTextureLevelPyramidData(void * dst,deUint32 dstLen,const tcu::TextureLevelPyramid & srcImage,vk::VkImageViewType viewType,std::vector<vk::VkBufferImageCopy> * copySlices)171 void writeTextureLevelPyramidData (void* dst, deUint32 dstLen, const tcu::TextureLevelPyramid& srcImage, vk::VkImageViewType viewType, std::vector<vk::VkBufferImageCopy>* copySlices)
172 {
173 // \note cube is copied face-by-face
174 const deUint32 arraySize = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (srcImage.getLevel(0).getHeight()) :
175 (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (srcImage.getLevel(0).getDepth()) :
176 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
177 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (srcImage.getLevel(0).getDepth()) :
178 ((deUint32)0);
179 deUint32 levelOffset = 0;
180
181 DE_ASSERT(arraySize != 0);
182
183 for (int level = 0; level < srcImage.getNumLevels(); ++level)
184 {
185 const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
186 const tcu::PixelBufferAccess dstAccess (srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(), (deUint8*)dst + levelOffset);
187 const deUint32 dataSize = srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
188 const deUint32 sliceDataSize = dataSize / arraySize;
189 const deInt32 sliceHeight = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1) : (srcAccess.getHeight());
190 const deInt32 sliceDepth = (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (srcAccess.getDepth()) : (1);
191 const tcu::IVec3 sliceSize (srcAccess.getWidth(), sliceHeight, sliceDepth);
192
193 // tightly packed
194 DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
195
196 for (int sliceNdx = 0; sliceNdx < (int)arraySize; ++sliceNdx)
197 {
198 const vk::VkBufferImageCopy copySlice =
199 {
200 (vk::VkDeviceSize)levelOffset + sliceNdx * sliceDataSize, // bufferOffset
201 (deUint32)sliceSize.x(), // bufferRowLength
202 (deUint32)sliceSize.y(), // bufferImageHeight
203 {
204 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
205 (deUint32)level, // mipLevel
206 (deUint32)sliceNdx, // arrayLayer
207 1u, // arraySize
208 }, // imageSubresource
209 {
210 0,
211 0,
212 0,
213 }, // imageOffset
214 {
215 (deUint32)sliceSize.x(),
216 (deUint32)sliceSize.y(),
217 (deUint32)sliceSize.z(),
218 } // imageExtent
219 };
220 copySlices->push_back(copySlice);
221 }
222
223 DE_ASSERT(arraySize * sliceDataSize == dataSize);
224
225 tcu::copy(dstAccess, srcAccess);
226 levelOffset += dataSize;
227 }
228
229 DE_ASSERT(dstLen == levelOffset);
230 DE_UNREF(dstLen);
231 }
232
allocateAndBindObjectMemory(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkBuffer buffer,vk::MemoryRequirement requirement)233 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory (const vk::DeviceInterface& vki, vk::VkDevice device, vk::Allocator& allocator, vk::VkBuffer buffer, vk::MemoryRequirement requirement)
234 {
235 const vk::VkMemoryRequirements requirements = vk::getBufferMemoryRequirements(vki, device, buffer);
236 de::MovePtr<vk::Allocation> allocation = allocator.allocate(requirements, requirement);
237
238 VK_CHECK(vki.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
239 return allocation;
240 }
241
allocateAndBindObjectMemory(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkImage image,vk::MemoryRequirement requirement)242 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory (const vk::DeviceInterface& vki, vk::VkDevice device, vk::Allocator& allocator, vk::VkImage image, vk::MemoryRequirement requirement)
243 {
244 const vk::VkMemoryRequirements requirements = vk::getImageMemoryRequirements(vki, device, image);
245 de::MovePtr<vk::Allocation> allocation = allocator.allocate(requirements, requirement);
246
247 VK_CHECK(vki.bindImageMemory(device, image, allocation->getMemory(), allocation->getOffset()));
248 return allocation;
249 }
250
makeDescriptorImageInfo(vk::VkSampler sampler)251 vk::VkDescriptorImageInfo makeDescriptorImageInfo (vk::VkSampler sampler)
252 {
253 return vk::makeDescriptorImageInfo(sampler, (vk::VkImageView)0, (vk::VkImageLayout)0);
254 }
255
makeDescriptorImageInfo(vk::VkImageView imageView,vk::VkImageLayout layout)256 vk::VkDescriptorImageInfo makeDescriptorImageInfo (vk::VkImageView imageView, vk::VkImageLayout layout)
257 {
258 return vk::makeDescriptorImageInfo((vk::VkSampler)0, imageView, layout);
259 }
260
drawQuadrantReferenceResult(const tcu::PixelBufferAccess & dst,const tcu::Vec4 & c1,const tcu::Vec4 & c2,const tcu::Vec4 & c3,const tcu::Vec4 & c4)261 void drawQuadrantReferenceResult (const tcu::PixelBufferAccess& dst, const tcu::Vec4& c1, const tcu::Vec4& c2, const tcu::Vec4& c3, const tcu::Vec4& c4)
262 {
263 tcu::clear(tcu::getSubregion(dst, 0, 0, dst.getWidth() / 2, dst.getHeight() / 2), c1);
264 tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, 0, dst.getWidth() - dst.getWidth() / 2, dst.getHeight() / 2), c2);
265 tcu::clear(tcu::getSubregion(dst, 0, dst.getHeight() / 2, dst.getWidth() / 2, dst.getHeight() - dst.getHeight() / 2), c3);
266 tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, dst.getHeight() / 2, dst.getWidth() - dst.getWidth() / 2, dst.getHeight() - dst.getHeight() / 2), c4);
267 }
268
269 class SingleTargetRenderInstance : public vkt::TestInstance
270 {
271 public:
272 SingleTargetRenderInstance (Context& context,
273 const tcu::UVec2& size);
274
275 private:
276 static vk::Move<vk::VkImage> createColorAttachment (const vk::DeviceInterface& vki,
277 vk::VkDevice device,
278 vk::Allocator& allocator,
279 const tcu::TextureFormat& format,
280 const tcu::UVec2& size,
281 de::MovePtr<vk::Allocation>* outAllocation);
282
283 static vk::Move<vk::VkImageView> createColorAttachmentView (const vk::DeviceInterface& vki,
284 vk::VkDevice device,
285 const tcu::TextureFormat& format,
286 vk::VkImage image);
287
288 static vk::Move<vk::VkRenderPass> createRenderPass (const vk::DeviceInterface& vki,
289 vk::VkDevice device,
290 const tcu::TextureFormat& format);
291
292 static vk::Move<vk::VkFramebuffer> createFramebuffer (const vk::DeviceInterface& vki,
293 vk::VkDevice device,
294 vk::VkRenderPass renderpass,
295 vk::VkImageView colorAttachmentView,
296 const tcu::UVec2& size);
297
298 static vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vki,
299 vk::VkDevice device,
300 deUint32 queueFamilyIndex);
301
302 virtual void logTestPlan (void) const = 0;
303 virtual void renderToTarget (void) = 0;
304 virtual tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const = 0;
305
306 void readRenderTarget (tcu::TextureLevel& dst);
307 tcu::TestStatus iterate (void);
308
309 protected:
310 const tcu::TextureFormat m_targetFormat;
311 const tcu::UVec2 m_targetSize;
312
313 const vk::DeviceInterface& m_vki;
314 const vk::VkDevice m_device;
315 const vk::VkQueue m_queue;
316 const deUint32 m_queueFamilyIndex;
317 vk::Allocator& m_allocator;
318 de::MovePtr<vk::Allocation> m_colorAttachmentMemory;
319 const vk::Unique<vk::VkImage> m_colorAttachmentImage;
320 const vk::Unique<vk::VkImageView> m_colorAttachmentView;
321 const vk::Unique<vk::VkRenderPass> m_renderPass;
322 const vk::Unique<vk::VkFramebuffer> m_framebuffer;
323 const vk::Unique<vk::VkCommandPool> m_cmdPool;
324
325 bool m_firstIteration;
326 };
327
SingleTargetRenderInstance(Context & context,const tcu::UVec2 & size)328 SingleTargetRenderInstance::SingleTargetRenderInstance (Context& context,
329 const tcu::UVec2& size)
330 : vkt::TestInstance (context)
331 , m_targetFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
332 , m_targetSize (size)
333 , m_vki (context.getDeviceInterface())
334 , m_device (context.getDevice())
335 , m_queue (context.getUniversalQueue())
336 , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
337 , m_allocator (context.getDefaultAllocator())
338 , m_colorAttachmentMemory (DE_NULL)
339 , m_colorAttachmentImage (createColorAttachment(m_vki, m_device, m_allocator, m_targetFormat, m_targetSize, &m_colorAttachmentMemory))
340 , m_colorAttachmentView (createColorAttachmentView(m_vki, m_device, m_targetFormat, *m_colorAttachmentImage))
341 , m_renderPass (createRenderPass(m_vki, m_device, m_targetFormat))
342 , m_framebuffer (createFramebuffer(m_vki, m_device, *m_renderPass, *m_colorAttachmentView, m_targetSize))
343 , m_cmdPool (createCommandPool(m_vki, m_device, context.getUniversalQueueFamilyIndex()))
344 , m_firstIteration (true)
345 {
346 }
347
createColorAttachment(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,const tcu::TextureFormat & format,const tcu::UVec2 & size,de::MovePtr<vk::Allocation> * outAllocation)348 vk::Move<vk::VkImage> SingleTargetRenderInstance::createColorAttachment (const vk::DeviceInterface& vki,
349 vk::VkDevice device,
350 vk::Allocator& allocator,
351 const tcu::TextureFormat& format,
352 const tcu::UVec2& size,
353 de::MovePtr<vk::Allocation>* outAllocation)
354 {
355 const vk::VkImageCreateInfo imageInfo =
356 {
357 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
358 DE_NULL,
359 (vk::VkImageCreateFlags)0,
360 vk::VK_IMAGE_TYPE_2D, // imageType
361 vk::mapTextureFormat(format), // format
362 { size.x(), size.y(), 1u }, // extent
363 1, // mipLevels
364 1, // arraySize
365 vk::VK_SAMPLE_COUNT_1_BIT, // samples
366 vk::VK_IMAGE_TILING_OPTIMAL, // tiling
367 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // usage
368 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
369 0u, // queueFamilyCount
370 DE_NULL, // pQueueFamilyIndices
371 vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
372 };
373
374 vk::Move<vk::VkImage> image (vk::createImage(vki, device, &imageInfo));
375 de::MovePtr<vk::Allocation> allocation (allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any));
376
377 *outAllocation = allocation;
378 return image;
379 }
380
createColorAttachmentView(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::TextureFormat & format,vk::VkImage image)381 vk::Move<vk::VkImageView> SingleTargetRenderInstance::createColorAttachmentView (const vk::DeviceInterface& vki,
382 vk::VkDevice device,
383 const tcu::TextureFormat& format,
384 vk::VkImage image)
385 {
386 const vk::VkImageViewCreateInfo createInfo =
387 {
388 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
389 DE_NULL,
390 (vk::VkImageViewCreateFlags)0,
391 image, // image
392 vk::VK_IMAGE_VIEW_TYPE_2D, // viewType
393 vk::mapTextureFormat(format), // format
394 vk::makeComponentMappingRGBA(),
395 {
396 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
397 0u, // baseMipLevel
398 1u, // mipLevels
399 0u, // baseArrayLayer
400 1u, // arraySize
401 },
402 };
403
404 return vk::createImageView(vki, device, &createInfo);
405 }
406
createRenderPass(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::TextureFormat & format)407 vk::Move<vk::VkRenderPass> SingleTargetRenderInstance::createRenderPass (const vk::DeviceInterface& vki,
408 vk::VkDevice device,
409 const tcu::TextureFormat& format)
410 {
411 const vk::VkAttachmentDescription attachmentDescription =
412 {
413 (vk::VkAttachmentDescriptionFlags)0,
414 vk::mapTextureFormat(format), // format
415 vk::VK_SAMPLE_COUNT_1_BIT, // samples
416 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp
417 vk::VK_ATTACHMENT_STORE_OP_STORE, // storeOp
418 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
419 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
420 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // initialLayout
421 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // finalLayout
422 };
423 const vk::VkAttachmentReference colorAttachment =
424 {
425 0u, // attachment
426 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // layout
427 };
428 const vk::VkAttachmentReference depthStencilAttachment =
429 {
430 vk::VK_NO_ATTACHMENT, // attachment
431 vk::VK_IMAGE_LAYOUT_UNDEFINED // layout
432 };
433 const vk::VkSubpassDescription subpass =
434 {
435 (vk::VkSubpassDescriptionFlags)0,
436 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
437 0u, // inputAttachmentCount
438 DE_NULL, // pInputAttachments
439 1u, // colorAttachmentCount
440 &colorAttachment, // pColorAttachments
441 DE_NULL, // pResolveAttachments
442 &depthStencilAttachment, // pDepthStencilAttachment
443 0u, // preserveAttachmentCount
444 DE_NULL // pPreserveAttachments
445 };
446 const vk::VkRenderPassCreateInfo renderPassCreateInfo =
447 {
448 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
449 DE_NULL,
450 (vk::VkRenderPassCreateFlags)0,
451 1u, // attachmentCount
452 &attachmentDescription, // pAttachments
453 1u, // subpassCount
454 &subpass, // pSubpasses
455 0u, // dependencyCount
456 DE_NULL, // pDependencies
457 };
458
459 return vk::createRenderPass(vki, device, &renderPassCreateInfo);
460 }
461
createFramebuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkRenderPass renderpass,vk::VkImageView colorAttachmentView,const tcu::UVec2 & size)462 vk::Move<vk::VkFramebuffer> SingleTargetRenderInstance::createFramebuffer (const vk::DeviceInterface& vki,
463 vk::VkDevice device,
464 vk::VkRenderPass renderpass,
465 vk::VkImageView colorAttachmentView,
466 const tcu::UVec2& size)
467 {
468 const vk::VkFramebufferCreateInfo framebufferCreateInfo =
469 {
470 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
471 DE_NULL,
472 (vk::VkFramebufferCreateFlags)0,
473 renderpass, // renderPass
474 1u, // attachmentCount
475 &colorAttachmentView, // pAttachments
476 size.x(), // width
477 size.y(), // height
478 1, // layers
479 };
480
481 return vk::createFramebuffer(vki, device, &framebufferCreateInfo);
482 }
483
createCommandPool(const vk::DeviceInterface & vki,vk::VkDevice device,deUint32 queueFamilyIndex)484 vk::Move<vk::VkCommandPool> SingleTargetRenderInstance::createCommandPool (const vk::DeviceInterface& vki,
485 vk::VkDevice device,
486 deUint32 queueFamilyIndex)
487 {
488 const vk::VkCommandPoolCreateInfo createInfo =
489 {
490 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
491 DE_NULL,
492 vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
493 queueFamilyIndex, // queueFamilyIndex
494 };
495 return vk::createCommandPool(vki, device, &createInfo);
496 }
497
readRenderTarget(tcu::TextureLevel & dst)498 void SingleTargetRenderInstance::readRenderTarget (tcu::TextureLevel& dst)
499 {
500 const deUint64 pixelDataSize = (deUint64)(m_targetSize.x() * m_targetSize.y() * m_targetFormat.getPixelSize());
501 const vk::VkBufferCreateInfo bufferCreateInfo =
502 {
503 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
504 DE_NULL,
505 0u, // flags
506 pixelDataSize, // size
507 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
508 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
509 0u, // queueFamilyCount
510 DE_NULL, // pQueueFamilyIndices
511 };
512 const vk::Unique<vk::VkBuffer> buffer (vk::createBuffer(m_vki, m_device, &bufferCreateInfo));
513 const vk::VkImageSubresourceRange fullSubrange =
514 {
515 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
516 0u, // baseMipLevel
517 1u, // mipLevels
518 0u, // baseArraySlice
519 1u, // arraySize
520 };
521 const vk::VkImageMemoryBarrier imageBarrier =
522 {
523 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
524 DE_NULL,
525 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask
526 vk::VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask
527 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
528 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout
529 vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
530 vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
531 *m_colorAttachmentImage, // image
532 fullSubrange, // subresourceRange
533 };
534 const vk::VkBufferMemoryBarrier memoryBarrier =
535 {
536 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
537 DE_NULL,
538 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
539 vk::VK_ACCESS_HOST_READ_BIT, // dstAccessMask
540 vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
541 vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
542 *buffer, // buffer
543 0u, // offset
544 (vk::VkDeviceSize)pixelDataSize // size
545 };
546 const vk::VkCommandBufferAllocateInfo cmdBufAllocInfo =
547 {
548 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
549 DE_NULL,
550 *m_cmdPool, // cmdPool
551 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
552 1u, // bufferCount
553 };
554 const vk::VkFenceCreateInfo fenceCreateInfo =
555 {
556 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
557 DE_NULL,
558 0u, // flags
559 };
560 const vk::VkCommandBufferBeginInfo cmdBufBeginInfo =
561 {
562 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
563 DE_NULL,
564 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags
565 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
566 };
567 const vk::VkImageSubresourceLayers firstSlice =
568 {
569 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspect
570 0, // mipLevel
571 0, // arrayLayer
572 1, // arraySize
573 };
574 const vk::VkBufferImageCopy copyRegion =
575 {
576 0u, // bufferOffset
577 m_targetSize.x(), // bufferRowLength
578 m_targetSize.y(), // bufferImageHeight
579 firstSlice, // imageSubresource
580 { 0, 0, 0 }, // imageOffset
581 { m_targetSize.x(), m_targetSize.y(), 1u } // imageExtent
582 };
583
584 const de::MovePtr<vk::Allocation> bufferMemory = allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible);
585
586 const vk::Unique<vk::VkCommandBuffer> cmd (vk::allocateCommandBuffer(m_vki, m_device, &cmdBufAllocInfo));
587 const vk::Unique<vk::VkFence> cmdCompleteFence (vk::createFence(m_vki, m_device, &fenceCreateInfo));
588 const deUint64 infiniteTimeout = ~(deUint64)0u;
589
590 // copy content to buffer
591 VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
592 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0,
593 0, (const vk::VkMemoryBarrier*)DE_NULL,
594 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
595 1, &imageBarrier);
596 m_vki.cmdCopyImageToBuffer(*cmd, *m_colorAttachmentImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1, ©Region);
597 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
598 0, (const vk::VkMemoryBarrier*)DE_NULL,
599 1, &memoryBarrier,
600 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
601 VK_CHECK(m_vki.endCommandBuffer(*cmd));
602
603 // wait for transfer to complete
604 {
605 const vk::VkSubmitInfo submitInfo =
606 {
607 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
608 DE_NULL,
609 0u,
610 (const vk::VkSemaphore*)0,
611 (const vk::VkPipelineStageFlags*)DE_NULL,
612 1u,
613 &cmd.get(),
614 0u,
615 (const vk::VkSemaphore*)0,
616 };
617
618 VK_CHECK(m_vki.queueSubmit(m_queue, 1, &submitInfo, *cmdCompleteFence));
619 }
620 VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
621
622 dst.setStorage(m_targetFormat, m_targetSize.x(), m_targetSize.y());
623
624 // copy data
625 invalidateMappedMemoryRange(m_vki, m_device, bufferMemory->getMemory(), bufferMemory->getOffset(), pixelDataSize);
626 tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferMemory->getHostPtr()));
627 }
628
iterate(void)629 tcu::TestStatus SingleTargetRenderInstance::iterate (void)
630 {
631 tcu::TextureLevel resultImage;
632
633 // log
634 if (m_firstIteration)
635 {
636 logTestPlan();
637 m_firstIteration = false;
638 }
639
640 // render
641 {
642 // transition to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
643 const vk::VkImageSubresourceRange fullSubrange =
644 {
645 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
646 0u, // baseMipLevel
647 1u, // mipLevels
648 0u, // baseArraySlice
649 1u, // arraySize
650 };
651 const vk::VkImageMemoryBarrier imageBarrier =
652 {
653 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
654 DE_NULL,
655 0u, // srcAccessMask
656 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask
657 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
658 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
659 vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
660 vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
661 *m_colorAttachmentImage, // image
662 fullSubrange, // subresourceRange
663 };
664 const vk::VkCommandBufferAllocateInfo cmdBufAllocInfo =
665 {
666 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
667 DE_NULL,
668 *m_cmdPool, // cmdPool
669 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
670 1u, // count
671 };
672 const vk::VkCommandBufferBeginInfo cmdBufBeginInfo =
673 {
674 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
675 DE_NULL,
676 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags
677 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
678 };
679 const vk::VkFenceCreateInfo fenceCreateInfo =
680 {
681 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
682 DE_NULL,
683 (vk::VkFenceCreateFlags)0,
684 };
685
686 const vk::Unique<vk::VkCommandBuffer> cmd (vk::allocateCommandBuffer(m_vki, m_device, &cmdBufAllocInfo));
687 const vk::Unique<vk::VkFence> fence (vk::createFence(m_vki, m_device, &fenceCreateInfo));
688 const deUint64 infiniteTimeout = ~(deUint64)0u;
689
690 VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
691 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
692 0, (const vk::VkMemoryBarrier*)DE_NULL,
693 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
694 1, &imageBarrier);
695 VK_CHECK(m_vki.endCommandBuffer(*cmd));
696
697 {
698 const vk::VkSubmitInfo submitInfo =
699 {
700 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
701 DE_NULL,
702 0u,
703 (const vk::VkSemaphore*)0,
704 (const vk::VkPipelineStageFlags*)DE_NULL,
705 1u,
706 &cmd.get(),
707 0u,
708 (const vk::VkSemaphore*)0,
709 };
710
711 VK_CHECK(m_vki.queueSubmit(m_queue, 1u, &submitInfo, *fence));
712 }
713 VK_CHECK(m_vki.waitForFences(m_device, 1u, &fence.get(), vk::VK_TRUE, infiniteTimeout));
714
715 // and then render to
716 renderToTarget();
717 }
718
719 // read and verify
720 readRenderTarget(resultImage);
721 return verifyResultImage(resultImage.getAccess());
722 }
723
724 class RenderInstanceShaders
725 {
726 public:
727 RenderInstanceShaders (const vk::DeviceInterface& vki,
728 vk::VkDevice device,
729 const vk::VkPhysicalDeviceFeatures& deviceFeatures,
730 const vk::BinaryCollection& programCollection);
731
hasTessellationStage(void) const732 inline bool hasTessellationStage (void) const { return *m_tessCtrlShaderModule != 0 || *m_tessEvalShaderModule != 0; }
getNumStages(void) const733 inline deUint32 getNumStages (void) const { return (deUint32)m_stageInfos.size(); }
getStages(void) const734 inline const vk::VkPipelineShaderStageCreateInfo* getStages (void) const { return &m_stageInfos[0]; }
735
736 private:
737 void addStage (const vk::DeviceInterface& vki,
738 vk::VkDevice device,
739 const vk::VkPhysicalDeviceFeatures& deviceFeatures,
740 const vk::BinaryCollection& programCollection,
741 const char* name,
742 vk::VkShaderStageFlagBits stage,
743 vk::Move<vk::VkShaderModule>* outModule);
744
745 vk::VkPipelineShaderStageCreateInfo getShaderStageCreateInfo (vk::VkShaderStageFlagBits stage, vk::VkShaderModule shader) const;
746
747 vk::Move<vk::VkShaderModule> m_vertexShaderModule;
748 vk::Move<vk::VkShaderModule> m_tessCtrlShaderModule;
749 vk::Move<vk::VkShaderModule> m_tessEvalShaderModule;
750 vk::Move<vk::VkShaderModule> m_geometryShaderModule;
751 vk::Move<vk::VkShaderModule> m_fragmentShaderModule;
752 std::vector<vk::VkPipelineShaderStageCreateInfo> m_stageInfos;
753 };
754
RenderInstanceShaders(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::VkPhysicalDeviceFeatures & deviceFeatures,const vk::BinaryCollection & programCollection)755 RenderInstanceShaders::RenderInstanceShaders (const vk::DeviceInterface& vki,
756 vk::VkDevice device,
757 const vk::VkPhysicalDeviceFeatures& deviceFeatures,
758 const vk::BinaryCollection& programCollection)
759 {
760 addStage(vki, device, deviceFeatures, programCollection, "vertex", vk::VK_SHADER_STAGE_VERTEX_BIT, &m_vertexShaderModule);
761 addStage(vki, device, deviceFeatures, programCollection, "tess_ctrl", vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, &m_tessCtrlShaderModule);
762 addStage(vki, device, deviceFeatures, programCollection, "tess_eval", vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, &m_tessEvalShaderModule);
763 addStage(vki, device, deviceFeatures, programCollection, "geometry", vk::VK_SHADER_STAGE_GEOMETRY_BIT, &m_geometryShaderModule);
764 addStage(vki, device, deviceFeatures, programCollection, "fragment", vk::VK_SHADER_STAGE_FRAGMENT_BIT, &m_fragmentShaderModule);
765
766 DE_ASSERT(!m_stageInfos.empty());
767 }
768
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)769 void RenderInstanceShaders::addStage (const vk::DeviceInterface& vki,
770 vk::VkDevice device,
771 const vk::VkPhysicalDeviceFeatures& deviceFeatures,
772 const vk::BinaryCollection& programCollection,
773 const char* name,
774 vk::VkShaderStageFlagBits stage,
775 vk::Move<vk::VkShaderModule>* outModule)
776 {
777 if (programCollection.contains(name))
778 {
779 if (vk::isShaderStageSupported(deviceFeatures, stage))
780 {
781 vk::Move<vk::VkShaderModule> module = createShaderModule(vki, device, programCollection.get(name), (vk::VkShaderModuleCreateFlags)0);
782
783 m_stageInfos.push_back(getShaderStageCreateInfo(stage, *module));
784 *outModule = module;
785 }
786 else
787 {
788 // Wait for the GPU to idle so that throwing the exception
789 // below doesn't free in-use GPU resource.
790 vki.deviceWaitIdle(device);
791 TCU_THROW(NotSupportedError, (de::toString(stage) + " is not supported").c_str());
792 }
793 }
794 }
795
getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,vk::VkShaderModule shader) const796 vk::VkPipelineShaderStageCreateInfo RenderInstanceShaders::getShaderStageCreateInfo (vk::VkShaderStageFlagBits stage, vk::VkShaderModule shader) const
797 {
798 const vk::VkPipelineShaderStageCreateInfo stageCreateInfo =
799 {
800 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
801 DE_NULL,
802 (vk::VkPipelineShaderStageCreateFlags)0,
803 stage, // stage
804 shader, // shader
805 "main",
806 DE_NULL, // pSpecializationInfo
807 };
808 return stageCreateInfo;
809 }
810
811 class SingleCmdRenderInstance : public SingleTargetRenderInstance
812 {
813 public:
814 SingleCmdRenderInstance (Context& context,
815 bool isPrimaryCmdBuf,
816 const tcu::UVec2& renderSize);
817
818 private:
819 vk::Move<vk::VkPipeline> createPipeline (vk::VkPipelineLayout pipelineLayout);
820
821 virtual vk::VkPipelineLayout getPipelineLayout (void) const = 0;
822 virtual void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const = 0;
823
824 void renderToTarget (void);
825
826 const bool m_isPrimaryCmdBuf;
827 };
828
SingleCmdRenderInstance(Context & context,bool isPrimaryCmdBuf,const tcu::UVec2 & renderSize)829 SingleCmdRenderInstance::SingleCmdRenderInstance (Context& context,
830 bool isPrimaryCmdBuf,
831 const tcu::UVec2& renderSize)
832 : SingleTargetRenderInstance (context, renderSize)
833 , m_isPrimaryCmdBuf (isPrimaryCmdBuf)
834 {
835 }
836
createPipeline(vk::VkPipelineLayout pipelineLayout)837 vk::Move<vk::VkPipeline> SingleCmdRenderInstance::createPipeline (vk::VkPipelineLayout pipelineLayout)
838 {
839 const RenderInstanceShaders shaderStages (m_vki, m_device, m_context.getDeviceFeatures(), m_context.getBinaryCollection());
840 const vk::VkPrimitiveTopology topology = shaderStages.hasTessellationStage() ? vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
841 const vk::VkPipelineVertexInputStateCreateInfo vertexInputState =
842 {
843 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
844 DE_NULL,
845 (vk::VkPipelineVertexInputStateCreateFlags)0,
846 0u, // bindingCount
847 DE_NULL, // pVertexBindingDescriptions
848 0u, // attributeCount
849 DE_NULL, // pVertexAttributeDescriptions
850 };
851 const vk::VkPipelineInputAssemblyStateCreateInfo iaState =
852 {
853 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
854 DE_NULL,
855 (vk::VkPipelineInputAssemblyStateCreateFlags)0,
856 topology, // topology
857 vk::VK_FALSE, // primitiveRestartEnable
858 };
859 const vk::VkPipelineTessellationStateCreateInfo tessState =
860 {
861 vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
862 DE_NULL,
863 (vk::VkPipelineTessellationStateCreateFlags)0,
864 3u, // patchControlPoints
865 };
866 const vk::VkViewport viewport =
867 {
868 0.0f, // originX
869 0.0f, // originY
870 float(m_targetSize.x()), // width
871 float(m_targetSize.y()), // height
872 0.0f, // minDepth
873 1.0f, // maxDepth
874 };
875 const vk::VkRect2D renderArea =
876 {
877 { 0, 0 }, // offset
878 { m_targetSize.x(), m_targetSize.y() }, // extent
879 };
880 const vk::VkPipelineViewportStateCreateInfo vpState =
881 {
882 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
883 DE_NULL,
884 (vk::VkPipelineViewportStateCreateFlags)0,
885 1u, // viewportCount
886 &viewport,
887 1u,
888 &renderArea,
889 };
890 const vk::VkPipelineRasterizationStateCreateInfo rsState =
891 {
892 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
893 DE_NULL,
894 (vk::VkPipelineRasterizationStateCreateFlags)0,
895 vk::VK_TRUE, // depthClipEnable
896 vk::VK_FALSE, // rasterizerDiscardEnable
897 vk::VK_POLYGON_MODE_FILL, // fillMode
898 vk::VK_CULL_MODE_NONE, // cullMode
899 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace
900 vk::VK_FALSE, // depthBiasEnable
901 0.0f, // depthBias
902 0.0f, // depthBiasClamp
903 0.0f, // slopeScaledDepthBias
904 1.0f, // lineWidth
905 };
906 const vk::VkSampleMask sampleMask = 0x01u;
907 const vk::VkPipelineMultisampleStateCreateInfo msState =
908 {
909 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
910 DE_NULL,
911 (vk::VkPipelineMultisampleStateCreateFlags)0,
912 vk::VK_SAMPLE_COUNT_1_BIT, // rasterSamples
913 vk::VK_FALSE, // sampleShadingEnable
914 0.0f, // minSampleShading
915 &sampleMask, // sampleMask
916 vk::VK_FALSE, // alphaToCoverageEnable
917 vk::VK_FALSE, // alphaToOneEnable
918 };
919 const vk::VkPipelineDepthStencilStateCreateInfo dsState =
920 {
921 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
922 DE_NULL,
923 (vk::VkPipelineDepthStencilStateCreateFlags)0,
924 vk::VK_FALSE, // depthTestEnable
925 vk::VK_FALSE, // depthWriteEnable
926 vk::VK_COMPARE_OP_ALWAYS, // depthCompareOp
927 vk::VK_FALSE, // depthBoundsTestEnable
928 vk::VK_FALSE, // stencilTestEnable
929 { vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u }, // front
930 { vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u }, // back
931 -1.0f, // minDepthBounds
932 +1.0f, // maxDepthBounds
933 };
934 const vk::VkPipelineColorBlendAttachmentState cbAttachment =
935 {
936 vk::VK_FALSE, // blendEnable
937 vk::VK_BLEND_FACTOR_ZERO, // srcBlendColor
938 vk::VK_BLEND_FACTOR_ZERO, // destBlendColor
939 vk::VK_BLEND_OP_ADD, // blendOpColor
940 vk::VK_BLEND_FACTOR_ZERO, // srcBlendAlpha
941 vk::VK_BLEND_FACTOR_ZERO, // destBlendAlpha
942 vk::VK_BLEND_OP_ADD, // blendOpAlpha
943 (vk::VK_COLOR_COMPONENT_R_BIT |
944 vk::VK_COLOR_COMPONENT_G_BIT |
945 vk::VK_COLOR_COMPONENT_B_BIT |
946 vk::VK_COLOR_COMPONENT_A_BIT), // channelWriteMask
947 };
948 const vk::VkPipelineColorBlendStateCreateInfo cbState =
949 {
950 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
951 DE_NULL,
952 (vk::VkPipelineColorBlendStateCreateFlags)0,
953 vk::VK_FALSE, // logicOpEnable
954 vk::VK_LOGIC_OP_CLEAR, // logicOp
955 1u, // attachmentCount
956 &cbAttachment, // pAttachments
957 { 0.0f, 0.0f, 0.0f, 0.0f }, // blendConst
958 };
959 const vk::VkGraphicsPipelineCreateInfo createInfo =
960 {
961 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
962 DE_NULL,
963 (vk::VkPipelineCreateFlags)0,
964 shaderStages.getNumStages(), // stageCount
965 shaderStages.getStages(), // pStages
966 &vertexInputState, // pVertexInputState
967 &iaState, // pInputAssemblyState
968 (shaderStages.hasTessellationStage() ? &tessState : DE_NULL), // pTessellationState
969 &vpState, // pViewportState
970 &rsState, // pRasterState
971 &msState, // pMultisampleState
972 &dsState, // pDepthStencilState
973 &cbState, // pColorBlendState
974 (const vk::VkPipelineDynamicStateCreateInfo*)DE_NULL, // pDynamicState
975 pipelineLayout, // layout
976 *m_renderPass, // renderPass
977 0u, // subpass
978 (vk::VkPipeline)0, // basePipelineHandle
979 0u, // basePipelineIndex
980 };
981 return createGraphicsPipeline(m_vki, m_device, (vk::VkPipelineCache)0u, &createInfo);
982 }
983
renderToTarget(void)984 void SingleCmdRenderInstance::renderToTarget (void)
985 {
986 const vk::VkRect2D renderArea =
987 {
988 { 0, 0 }, // offset
989 { m_targetSize.x(), m_targetSize.y() }, // extent
990 };
991 const vk::VkCommandBufferAllocateInfo mainCmdBufCreateInfo =
992 {
993 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
994 DE_NULL,
995 *m_cmdPool, // cmdPool
996 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
997 1u, // count
998 };
999 const vk::VkCommandBufferBeginInfo mainCmdBufBeginInfo =
1000 {
1001 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1002 DE_NULL,
1003 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags
1004 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
1005 };
1006 const vk::VkCommandBufferAllocateInfo passCmdBufCreateInfo =
1007 {
1008 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
1009 DE_NULL,
1010 *m_cmdPool, // cmdPool
1011 vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY, // level
1012 1u, // count
1013 };
1014 const vk::VkCommandBufferInheritanceInfo passCmdBufInheritInfo =
1015 {
1016 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
1017 DE_NULL,
1018 (vk::VkRenderPass)*m_renderPass, // renderPass
1019 0u, // subpass
1020 (vk::VkFramebuffer)*m_framebuffer, // framebuffer
1021 vk::VK_FALSE, // occlusionQueryEnable
1022 (vk::VkQueryControlFlags)0,
1023 (vk::VkQueryPipelineStatisticFlags)0,
1024 };
1025 const vk::VkCommandBufferBeginInfo passCmdBufBeginInfo =
1026 {
1027 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1028 DE_NULL,
1029 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT |
1030 vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // flags
1031 &passCmdBufInheritInfo,
1032 };
1033 const vk::VkFenceCreateInfo fenceCreateInfo =
1034 {
1035 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1036 DE_NULL,
1037 0u, // flags
1038 };
1039 const vk::VkClearValue clearValue = vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f);
1040 const vk::VkRenderPassBeginInfo renderPassBeginInfo =
1041 {
1042 vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1043 DE_NULL,
1044 *m_renderPass, // renderPass
1045 *m_framebuffer, // framebuffer
1046 renderArea, // renderArea
1047 1u, // clearValueCount
1048 &clearValue, // pClearValues
1049 };
1050
1051 const vk::VkPipelineLayout pipelineLayout (getPipelineLayout());
1052 const vk::Unique<vk::VkPipeline> pipeline (createPipeline(pipelineLayout));
1053 const vk::Unique<vk::VkCommandBuffer> mainCmd (vk::allocateCommandBuffer(m_vki, m_device, &mainCmdBufCreateInfo));
1054 const vk::Unique<vk::VkCommandBuffer> passCmd ((m_isPrimaryCmdBuf) ? (vk::Move<vk::VkCommandBuffer>()) : (vk::allocateCommandBuffer(m_vki, m_device, &passCmdBufCreateInfo)));
1055 const vk::Unique<vk::VkFence> fence (vk::createFence(m_vki, m_device, &fenceCreateInfo));
1056 const deUint64 infiniteTimeout = ~(deUint64)0u;
1057 const vk::VkSubpassContents passContents = (m_isPrimaryCmdBuf) ? (vk::VK_SUBPASS_CONTENTS_INLINE) : (vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1058
1059 VK_CHECK(m_vki.beginCommandBuffer(*mainCmd, &mainCmdBufBeginInfo));
1060 m_vki.cmdBeginRenderPass(*mainCmd, &renderPassBeginInfo, passContents);
1061
1062 if (m_isPrimaryCmdBuf)
1063 {
1064 m_vki.cmdBindPipeline(*mainCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1065 writeDrawCmdBuffer(*mainCmd);
1066 }
1067 else
1068 {
1069 VK_CHECK(m_vki.beginCommandBuffer(*passCmd, &passCmdBufBeginInfo));
1070 m_vki.cmdBindPipeline(*passCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1071 writeDrawCmdBuffer(*passCmd);
1072 VK_CHECK(m_vki.endCommandBuffer(*passCmd));
1073
1074 m_vki.cmdExecuteCommands(*mainCmd, 1, &passCmd.get());
1075 }
1076
1077 m_vki.cmdEndRenderPass(*mainCmd);
1078 VK_CHECK(m_vki.endCommandBuffer(*mainCmd));
1079
1080 // submit and wait for them to finish before exiting scope. (Killing in-flight objects is a no-no).
1081 {
1082 const vk::VkSubmitInfo submitInfo =
1083 {
1084 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1085 DE_NULL,
1086 0u,
1087 (const vk::VkSemaphore*)0,
1088 (const vk::VkPipelineStageFlags*)DE_NULL,
1089 1u,
1090 &mainCmd.get(),
1091 0u,
1092 (const vk::VkSemaphore*)0,
1093 };
1094 VK_CHECK(m_vki.queueSubmit(m_queue, 1, &submitInfo, *fence));
1095 }
1096 VK_CHECK(m_vki.waitForFences(m_device, 1, &fence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
1097 }
1098
1099 enum ShaderInputInterface
1100 {
1101 SHADER_INPUT_SINGLE_DESCRIPTOR = 0, //!< one descriptor
1102 SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS, //!< multiple descriptors with contiguous binding id's
1103 SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS, //!< multiple descriptors with discontiguous binding id's
1104 SHADER_INPUT_DESCRIPTOR_ARRAY, //!< descriptor array
1105
1106 SHADER_INPUT_LAST
1107 };
1108
getInterfaceNumResources(ShaderInputInterface shaderInterface)1109 deUint32 getInterfaceNumResources (ShaderInputInterface shaderInterface)
1110 {
1111 switch (shaderInterface)
1112 {
1113 case SHADER_INPUT_SINGLE_DESCRIPTOR: return 1u;
1114 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: return 2u;
1115 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS: return 2u;
1116 case SHADER_INPUT_DESCRIPTOR_ARRAY: return 2u;
1117
1118 default:
1119 DE_FATAL("Impossible");
1120 return 0u;
1121 }
1122 }
1123
1124 class BufferRenderInstance : public SingleCmdRenderInstance
1125 {
1126 public:
1127 BufferRenderInstance (Context& context,
1128 bool isPrimaryCmdBuf,
1129 vk::VkDescriptorType descriptorType,
1130 vk::VkShaderStageFlags stageFlags,
1131 ShaderInputInterface shaderInterface,
1132 bool viewOffset,
1133 bool dynamicOffset,
1134 bool dynamicOffsetNonZero);
1135
1136 static vk::Move<vk::VkBuffer> createSourceBuffer (const vk::DeviceInterface& vki,
1137 vk::VkDevice device,
1138 vk::Allocator& allocator,
1139 vk::VkDescriptorType descriptorType,
1140 deUint32 offset,
1141 deUint32 bufferSize,
1142 de::MovePtr<vk::Allocation>* outMemory);
1143
1144 static vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vki,
1145 vk::VkDevice device,
1146 vk::VkDescriptorType descriptorType,
1147 ShaderInputInterface shaderInterface);
1148
1149 static vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vki,
1150 vk::VkDevice device,
1151 vk::VkDescriptorType descriptorType,
1152 ShaderInputInterface shaderInterface,
1153 vk::VkShaderStageFlags stageFlags);
1154
1155 static vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vki,
1156 vk::VkDevice device,
1157 vk::VkDescriptorSetLayout descriptorSetLayout,
1158 vk::VkDescriptorPool descriptorPool,
1159 vk::VkDescriptorType descriptorType,
1160 ShaderInputInterface shaderInterface,
1161 vk::VkBuffer sourceBufferA,
1162 const deUint32 viewOffsetA,
1163 vk::VkBuffer sourceBufferB,
1164 const deUint32 viewOffsetB);
1165
1166 static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki,
1167 vk::VkDevice device,
1168 vk::VkDescriptorSetLayout descriptorSetLayout);
1169
1170 void logTestPlan (void) const;
1171 vk::VkPipelineLayout getPipelineLayout (void) const;
1172 void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const;
1173 tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const;
1174
1175 enum
1176 {
1177 RENDER_SIZE = 128,
1178 BUFFER_DATA_SIZE = 8 * sizeof(float),
1179 BUFFER_SIZE_A = 2048, //!< a lot more than required
1180 BUFFER_SIZE_B = 2560, //!< a lot more than required
1181
1182 STATIC_OFFSET_VALUE_A = 256,
1183 DYNAMIC_OFFSET_VALUE_A = 512,
1184 STATIC_OFFSET_VALUE_B = 1024,
1185 DYNAMIC_OFFSET_VALUE_B = 768,
1186 };
1187
1188 const vk::VkDescriptorType m_descriptorType;
1189 const ShaderInputInterface m_shaderInterface;
1190 const bool m_setViewOffset;
1191 const bool m_setDynamicOffset;
1192 const bool m_dynamicOffsetNonZero;
1193 const vk::VkShaderStageFlags m_stageFlags;
1194
1195 const deUint32 m_viewOffsetA;
1196 const deUint32 m_viewOffsetB;
1197 const deUint32 m_dynamicOffsetA;
1198 const deUint32 m_dynamicOffsetB;
1199 const deUint32 m_effectiveOffsetA;
1200 const deUint32 m_effectiveOffsetB;
1201 const deUint32 m_bufferSizeA;
1202 const deUint32 m_bufferSizeB;
1203
1204 de::MovePtr<vk::Allocation> m_bufferMemoryA;
1205 de::MovePtr<vk::Allocation> m_bufferMemoryB;
1206 const vk::Unique<vk::VkBuffer> m_sourceBufferA;
1207 const vk::Unique<vk::VkBuffer> m_sourceBufferB;
1208 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
1209 const vk::Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
1210 const vk::Unique<vk::VkDescriptorSet> m_descriptorSet;
1211 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
1212 };
1213
BufferRenderInstance(Context & context,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags stageFlags,ShaderInputInterface shaderInterface,bool viewOffset,bool dynamicOffset,bool dynamicOffsetNonZero)1214 BufferRenderInstance::BufferRenderInstance (Context& context,
1215 bool isPrimaryCmdBuf,
1216 vk::VkDescriptorType descriptorType,
1217 vk::VkShaderStageFlags stageFlags,
1218 ShaderInputInterface shaderInterface,
1219 bool viewOffset,
1220 bool dynamicOffset,
1221 bool dynamicOffsetNonZero)
1222 : SingleCmdRenderInstance (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
1223 , m_descriptorType (descriptorType)
1224 , m_shaderInterface (shaderInterface)
1225 , m_setViewOffset (viewOffset)
1226 , m_setDynamicOffset (dynamicOffset)
1227 , m_dynamicOffsetNonZero (dynamicOffsetNonZero)
1228 , m_stageFlags (stageFlags)
1229 , m_viewOffsetA ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u))
1230 , m_viewOffsetB ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u))
1231 , m_dynamicOffsetA ((dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_A) : (0u))
1232 , m_dynamicOffsetB ((dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_B) : (0u))
1233 , m_effectiveOffsetA ((isDynamicDescriptorType(m_descriptorType)) ? (m_viewOffsetA + m_dynamicOffsetA) : (m_viewOffsetA))
1234 , m_effectiveOffsetB ((isDynamicDescriptorType(m_descriptorType)) ? (m_viewOffsetB + m_dynamicOffsetB) : (m_viewOffsetB))
1235 , m_bufferSizeA (BUFFER_SIZE_A)
1236 , m_bufferSizeB (BUFFER_SIZE_B)
1237 , m_bufferMemoryA (DE_NULL)
1238 , m_bufferMemoryB (DE_NULL)
1239 , m_sourceBufferA (createSourceBuffer(m_vki, m_device, m_allocator, m_descriptorType, m_effectiveOffsetA, m_bufferSizeA, &m_bufferMemoryA))
1240 , m_sourceBufferB ((getInterfaceNumResources(m_shaderInterface) == 1u)
1241 ? vk::Move<vk::VkBuffer>()
1242 : createSourceBuffer(m_vki, m_device, m_allocator, m_descriptorType, m_effectiveOffsetB, m_bufferSizeB, &m_bufferMemoryB))
1243 , m_descriptorPool (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
1244 , m_descriptorSetLayout (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
1245 , m_descriptorSet (createDescriptorSet(m_vki, m_device, *m_descriptorSetLayout, *m_descriptorPool, m_descriptorType, m_shaderInterface, *m_sourceBufferA, m_viewOffsetA, *m_sourceBufferB, m_viewOffsetB))
1246 , m_pipelineLayout (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
1247 {
1248 if (m_setDynamicOffset)
1249 DE_ASSERT(isDynamicDescriptorType(m_descriptorType));
1250 if (m_dynamicOffsetNonZero)
1251 DE_ASSERT(m_setDynamicOffset);
1252 }
1253
createSourceBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,deUint32 offset,deUint32 bufferSize,de::MovePtr<vk::Allocation> * outMemory)1254 vk::Move<vk::VkBuffer> BufferRenderInstance::createSourceBuffer (const vk::DeviceInterface& vki,
1255 vk::VkDevice device,
1256 vk::Allocator& allocator,
1257 vk::VkDescriptorType descriptorType,
1258 deUint32 offset,
1259 deUint32 bufferSize,
1260 de::MovePtr<vk::Allocation>* outMemory)
1261 {
1262 static const float s_colors[] =
1263 {
1264 0.0f, 1.0f, 0.0f, 1.0f, // green
1265 1.0f, 1.0f, 0.0f, 1.0f, // yellow
1266 };
1267 DE_STATIC_ASSERT(sizeof(s_colors) == BUFFER_DATA_SIZE);
1268 DE_ASSERT(offset + BUFFER_DATA_SIZE <= bufferSize);
1269 DE_ASSERT(offset % sizeof(float) == 0);
1270 DE_ASSERT(bufferSize % sizeof(float) == 0);
1271
1272 const bool isUniformBuffer = isUniformDescriptorType(descriptorType);
1273 const vk::VkBufferUsageFlags usageFlags = (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1274 const float preGuardValue = 0.5f;
1275 const float postGuardValue = 0.75f;
1276 const vk::VkBufferCreateInfo bufferCreateInfo =
1277 {
1278 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1279 DE_NULL,
1280 0u, // flags
1281 bufferSize, // size
1282 usageFlags, // usage
1283 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
1284 0u, // queueFamilyCount
1285 DE_NULL, // pQueueFamilyIndices
1286 };
1287 vk::Move<vk::VkBuffer> buffer (vk::createBuffer(vki, device, &bufferCreateInfo));
1288 de::MovePtr<vk::Allocation> bufferMemory = allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible);
1289 void* const mapPtr = bufferMemory->getHostPtr();
1290
1291 // guard with interesting values
1292 for (size_t preGuardOffset = 0; preGuardOffset + sizeof(float) <= (size_t)offset; preGuardOffset += sizeof(float))
1293 deMemcpy((deUint8*)mapPtr + preGuardOffset, &preGuardValue, sizeof(float));
1294
1295 deMemcpy((deUint8*)mapPtr + offset, s_colors, sizeof(s_colors));
1296 for (size_t postGuardOffset = (size_t)offset + sizeof(s_colors); postGuardOffset + sizeof(float) <= (size_t)bufferSize; postGuardOffset += sizeof(float))
1297 deMemcpy((deUint8*)mapPtr + postGuardOffset, &postGuardValue, sizeof(float));
1298 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
1299
1300 flushMappedMemoryRange(vki, device, bufferMemory->getMemory(), bufferMemory->getOffset(), bufferSize);
1301
1302 // Flushed host-visible memory is automatically made available to the GPU, no barrier is needed.
1303
1304 *outMemory = bufferMemory;
1305 return buffer;
1306 }
1307
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface)1308 vk::Move<vk::VkDescriptorPool> BufferRenderInstance::createDescriptorPool (const vk::DeviceInterface& vki,
1309 vk::VkDevice device,
1310 vk::VkDescriptorType descriptorType,
1311 ShaderInputInterface shaderInterface)
1312 {
1313 return vk::DescriptorPoolBuilder()
1314 .addType(descriptorType, getInterfaceNumResources(shaderInterface))
1315 .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
1316 }
1317
createDescriptorSetLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags)1318 vk::Move<vk::VkDescriptorSetLayout> BufferRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface& vki,
1319 vk::VkDevice device,
1320 vk::VkDescriptorType descriptorType,
1321 ShaderInputInterface shaderInterface,
1322 vk::VkShaderStageFlags stageFlags)
1323 {
1324 vk::DescriptorSetLayoutBuilder builder;
1325
1326 switch (shaderInterface)
1327 {
1328 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1329 builder.addSingleBinding(descriptorType, stageFlags);
1330 break;
1331
1332 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1333 builder.addSingleBinding(descriptorType, stageFlags);
1334 builder.addSingleBinding(descriptorType, stageFlags);
1335 break;
1336
1337 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1338 builder.addArrayBinding(descriptorType, 2u, stageFlags);
1339 break;
1340
1341 default:
1342 DE_FATAL("Impossible");
1343 }
1344
1345 return builder.build(vki, device);
1346 }
1347
createDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorSetLayout descriptorSetLayout,vk::VkDescriptorPool descriptorPool,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkBuffer bufferA,deUint32 offsetA,vk::VkBuffer bufferB,deUint32 offsetB)1348 vk::Move<vk::VkDescriptorSet> BufferRenderInstance::createDescriptorSet (const vk::DeviceInterface& vki,
1349 vk::VkDevice device,
1350 vk::VkDescriptorSetLayout descriptorSetLayout,
1351 vk::VkDescriptorPool descriptorPool,
1352 vk::VkDescriptorType descriptorType,
1353 ShaderInputInterface shaderInterface,
1354 vk::VkBuffer bufferA,
1355 deUint32 offsetA,
1356 vk::VkBuffer bufferB,
1357 deUint32 offsetB)
1358 {
1359 const vk::VkDescriptorBufferInfo bufferInfos[2] =
1360 {
1361 vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1362 vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1363 };
1364 const vk::VkDescriptorSetAllocateInfo allocInfo =
1365 {
1366 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1367 DE_NULL,
1368 descriptorPool,
1369 1u,
1370 &descriptorSetLayout
1371 };
1372
1373 vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
1374 vk::DescriptorSetUpdateBuilder builder;
1375
1376 switch (shaderInterface)
1377 {
1378 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1379 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &bufferInfos[0]);
1380 break;
1381
1382 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1383 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &bufferInfos[0]);
1384 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &bufferInfos[1]);
1385 break;
1386
1387 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1388 builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, bufferInfos);
1389 break;
1390
1391 default:
1392 DE_FATAL("Impossible");
1393 }
1394
1395 builder.update(vki, device);
1396 return descriptorSet;
1397 }
1398
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorSetLayout descriptorSetLayout)1399 vk::Move<vk::VkPipelineLayout> BufferRenderInstance::createPipelineLayout (const vk::DeviceInterface& vki,
1400 vk::VkDevice device,
1401 vk::VkDescriptorSetLayout descriptorSetLayout)
1402 {
1403 const vk::VkPipelineLayoutCreateInfo createInfo =
1404 {
1405 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1406 DE_NULL,
1407 (vk::VkPipelineLayoutCreateFlags)0,
1408 1, // descriptorSetCount
1409 &descriptorSetLayout, // pSetLayouts
1410 0u, // pushConstantRangeCount
1411 DE_NULL, // pPushConstantRanges
1412 };
1413
1414 return vk::createPipelineLayout(vki, device, &createInfo);
1415 }
1416
logTestPlan(void) const1417 void BufferRenderInstance::logTestPlan (void) const
1418 {
1419 std::ostringstream msg;
1420
1421 msg << "Rendering 2x2 yellow-green grid.\n"
1422 << "Single descriptor set. Descriptor set contains "
1423 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
1424 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
1425 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
1426 (const char*)DE_NULL)
1427 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
1428 << "Buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
1429
1430 if (isDynamicDescriptorType(m_descriptorType))
1431 {
1432 if (m_setDynamicOffset)
1433 {
1434 msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
1435 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
1436 }
1437 else
1438 {
1439 msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
1440 }
1441 }
1442
1443 if (m_stageFlags == 0u)
1444 {
1445 msg << "Descriptors are not accessed in any shader stage.\n";
1446 }
1447 else
1448 {
1449 msg << "Descriptors are accessed in {"
1450 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
1451 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
1452 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
1453 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
1454 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : (""))
1455 << " } stages.\n";
1456 }
1457
1458 m_context.getTestContext().getLog()
1459 << tcu::TestLog::Message
1460 << msg.str()
1461 << tcu::TestLog::EndMessage;
1462 }
1463
getPipelineLayout(void) const1464 vk::VkPipelineLayout BufferRenderInstance::getPipelineLayout (void) const
1465 {
1466 return *m_pipelineLayout;
1467 }
1468
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const1469 void BufferRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
1470 {
1471 // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
1472 const deUint32 dynamicOffsets[] =
1473 {
1474 m_dynamicOffsetA,
1475 m_dynamicOffsetB,
1476 };
1477 const deUint32 numOffsets = (!m_setDynamicOffset) ? (0u) : (getInterfaceNumResources(m_shaderInterface));
1478 const deUint32* const dynamicOffsetPtr = (!m_setDynamicOffset) ? (DE_NULL) : (dynamicOffsets);
1479
1480 m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), numOffsets, dynamicOffsetPtr);
1481 m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
1482 }
1483
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const1484 tcu::TestStatus BufferRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
1485 {
1486 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
1487 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f);
1488 tcu::Surface reference (m_targetSize.x(), m_targetSize.y());
1489
1490 drawQuadrantReferenceResult(reference.getAccess(), yellow, green, green, yellow);
1491
1492 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
1493 return tcu::TestStatus::fail("Image verification failed");
1494 else
1495 return tcu::TestStatus::pass("Pass");
1496 }
1497
1498 class ComputeInstanceResultBuffer
1499 {
1500 public:
1501 enum
1502 {
1503 DATA_SIZE = sizeof(tcu::Vec4[4])
1504 };
1505
1506 ComputeInstanceResultBuffer (const vk::DeviceInterface& vki,
1507 vk::VkDevice device,
1508 vk::Allocator& allocator);
1509
1510 void readResultContentsTo (tcu::Vec4 (*results)[4]) const;
1511
getBuffer(void) const1512 inline vk::VkBuffer getBuffer (void) const { return *m_buffer; }
getResultReadBarrier(void) const1513 inline const vk::VkBufferMemoryBarrier* getResultReadBarrier (void) const { return &m_bufferBarrier; }
1514
1515 private:
1516 static vk::Move<vk::VkBuffer> createResultBuffer (const vk::DeviceInterface& vki,
1517 vk::VkDevice device,
1518 vk::Allocator& allocator,
1519 de::MovePtr<vk::Allocation>* outAllocation);
1520
1521 static vk::VkBufferMemoryBarrier createResultBufferBarrier (vk::VkBuffer buffer);
1522
1523 const vk::DeviceInterface& m_vki;
1524 const vk::VkDevice m_device;
1525
1526 de::MovePtr<vk::Allocation> m_bufferMem;
1527 const vk::Unique<vk::VkBuffer> m_buffer;
1528 const vk::VkBufferMemoryBarrier m_bufferBarrier;
1529 };
1530
ComputeInstanceResultBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator)1531 ComputeInstanceResultBuffer::ComputeInstanceResultBuffer (const vk::DeviceInterface& vki,
1532 vk::VkDevice device,
1533 vk::Allocator& allocator)
1534 : m_vki (vki)
1535 , m_device (device)
1536 , m_bufferMem (DE_NULL)
1537 , m_buffer (createResultBuffer(m_vki, m_device, allocator, &m_bufferMem))
1538 , m_bufferBarrier (createResultBufferBarrier(*m_buffer))
1539 {
1540 }
1541
readResultContentsTo(tcu::Vec4 (* results)[4]) const1542 void ComputeInstanceResultBuffer::readResultContentsTo (tcu::Vec4 (*results)[4]) const
1543 {
1544 invalidateMappedMemoryRange(m_vki, m_device, m_bufferMem->getMemory(), m_bufferMem->getOffset(), sizeof(*results));
1545 deMemcpy(*results, m_bufferMem->getHostPtr(), sizeof(*results));
1546 }
1547
createResultBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,de::MovePtr<vk::Allocation> * outAllocation)1548 vk::Move<vk::VkBuffer> ComputeInstanceResultBuffer::createResultBuffer (const vk::DeviceInterface& vki,
1549 vk::VkDevice device,
1550 vk::Allocator& allocator,
1551 de::MovePtr<vk::Allocation>* outAllocation)
1552 {
1553 const vk::VkBufferCreateInfo createInfo =
1554 {
1555 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1556 DE_NULL,
1557 0u, // flags
1558 (vk::VkDeviceSize)DATA_SIZE, // size
1559 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // usage
1560 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
1561 0u, // queueFamilyCount
1562 DE_NULL, // pQueueFamilyIndices
1563 };
1564 vk::Move<vk::VkBuffer> buffer (vk::createBuffer(vki, device, &createInfo));
1565 de::MovePtr<vk::Allocation> allocation (allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
1566 const float clearValue = -1.0f;
1567 void* mapPtr = allocation->getHostPtr();
1568
1569 for (size_t offset = 0; offset < DATA_SIZE; offset += sizeof(float))
1570 deMemcpy(((deUint8*)mapPtr) + offset, &clearValue, sizeof(float));
1571
1572 flushMappedMemoryRange(vki, device, allocation->getMemory(), allocation->getOffset(), (vk::VkDeviceSize)DATA_SIZE);
1573
1574 *outAllocation = allocation;
1575 return buffer;
1576 }
1577
createResultBufferBarrier(vk::VkBuffer buffer)1578 vk::VkBufferMemoryBarrier ComputeInstanceResultBuffer::createResultBufferBarrier (vk::VkBuffer buffer)
1579 {
1580 const vk::VkBufferMemoryBarrier bufferBarrier =
1581 {
1582 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1583 DE_NULL,
1584 vk::VK_ACCESS_SHADER_WRITE_BIT, // outputMask
1585 vk::VK_ACCESS_HOST_READ_BIT, // inputMask
1586 vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
1587 vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
1588 buffer, // buffer
1589 (vk::VkDeviceSize)0u, // offset
1590 DATA_SIZE, // size
1591 };
1592 return bufferBarrier;
1593 }
1594
1595 class ComputePipeline
1596 {
1597 public:
1598 ComputePipeline (const vk::DeviceInterface& vki,
1599 vk::VkDevice device,
1600 const vk::BinaryCollection& programCollection,
1601 deUint32 numDescriptorSets,
1602 const vk::VkDescriptorSetLayout* descriptorSetLayouts);
1603
getPipeline(void) const1604 inline vk::VkPipeline getPipeline (void) const { return *m_pipeline; };
getPipelineLayout(void) const1605 inline vk::VkPipelineLayout getPipelineLayout (void) const { return *m_pipelineLayout; };
1606
1607 private:
1608 static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki,
1609 vk::VkDevice device,
1610 deUint32 numDescriptorSets,
1611 const vk::VkDescriptorSetLayout* descriptorSetLayouts);
1612
1613 static vk::Move<vk::VkPipeline> createPipeline (const vk::DeviceInterface& vki,
1614 vk::VkDevice device,
1615 const vk::BinaryCollection& programCollection,
1616 vk::VkPipelineLayout layout);
1617
1618 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
1619 const vk::Unique<vk::VkPipeline> m_pipeline;
1620 };
1621
ComputePipeline(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::BinaryCollection & programCollection,deUint32 numDescriptorSets,const vk::VkDescriptorSetLayout * descriptorSetLayouts)1622 ComputePipeline::ComputePipeline (const vk::DeviceInterface& vki,
1623 vk::VkDevice device,
1624 const vk::BinaryCollection& programCollection,
1625 deUint32 numDescriptorSets,
1626 const vk::VkDescriptorSetLayout* descriptorSetLayouts)
1627 : m_pipelineLayout (createPipelineLayout(vki, device, numDescriptorSets, descriptorSetLayouts))
1628 , m_pipeline (createPipeline(vki, device, programCollection, *m_pipelineLayout))
1629 {
1630 }
1631
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,deUint32 numDescriptorSets,const vk::VkDescriptorSetLayout * descriptorSetLayouts)1632 vk::Move<vk::VkPipelineLayout> ComputePipeline::createPipelineLayout (const vk::DeviceInterface& vki,
1633 vk::VkDevice device,
1634 deUint32 numDescriptorSets,
1635 const vk::VkDescriptorSetLayout* descriptorSetLayouts)
1636 {
1637 const vk::VkPipelineLayoutCreateInfo createInfo =
1638 {
1639 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1640 DE_NULL,
1641 (vk::VkPipelineLayoutCreateFlags)0,
1642 numDescriptorSets, // descriptorSetCount
1643 descriptorSetLayouts, // pSetLayouts
1644 0u, // pushConstantRangeCount
1645 DE_NULL, // pPushConstantRanges
1646 };
1647 return vk::createPipelineLayout(vki, device, &createInfo);
1648 }
1649
createPipeline(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::BinaryCollection & programCollection,vk::VkPipelineLayout layout)1650 vk::Move<vk::VkPipeline> ComputePipeline::createPipeline (const vk::DeviceInterface& vki,
1651 vk::VkDevice device,
1652 const vk::BinaryCollection& programCollection,
1653 vk::VkPipelineLayout layout)
1654 {
1655 const vk::Unique<vk::VkShaderModule> computeModule (vk::createShaderModule(vki, device, programCollection.get("compute"), (vk::VkShaderModuleCreateFlags)0u));
1656 const vk::VkPipelineShaderStageCreateInfo cs =
1657 {
1658 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1659 DE_NULL,
1660 (vk::VkPipelineShaderStageCreateFlags)0,
1661 vk::VK_SHADER_STAGE_COMPUTE_BIT, // stage
1662 *computeModule, // shader
1663 "main",
1664 DE_NULL, // pSpecializationInfo
1665 };
1666 const vk::VkComputePipelineCreateInfo createInfo =
1667 {
1668 vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1669 DE_NULL,
1670 0u, // flags
1671 cs, // cs
1672 layout, // layout
1673 (vk::VkPipeline)0, // basePipelineHandle
1674 0u, // basePipelineIndex
1675 };
1676 return createComputePipeline(vki, device, (vk::VkPipelineCache)0u, &createInfo);
1677 }
1678
1679 class ComputeCommand
1680 {
1681 public:
1682 ComputeCommand (const vk::DeviceInterface& vki,
1683 vk::VkDevice device,
1684 vk::VkPipeline pipeline,
1685 vk::VkPipelineLayout pipelineLayout,
1686 const tcu::UVec3& numWorkGroups,
1687 int numDescriptorSets,
1688 const vk::VkDescriptorSet* descriptorSets,
1689 int numDynamicOffsets,
1690 const deUint32* dynamicOffsets,
1691 int numPreBarriers,
1692 const vk::VkBufferMemoryBarrier* preBarriers,
1693 int numPostBarriers,
1694 const vk::VkBufferMemoryBarrier* postBarriers);
1695
1696 void submitAndWait (deUint32 queueFamilyIndex, vk::VkQueue queue) const;
1697
1698 private:
1699 const vk::DeviceInterface& m_vki;
1700 const vk::VkDevice m_device;
1701 const vk::VkPipeline m_pipeline;
1702 const vk::VkPipelineLayout m_pipelineLayout;
1703 const tcu::UVec3 m_numWorkGroups;
1704 const int m_numDescriptorSets;
1705 const vk::VkDescriptorSet* const m_descriptorSets;
1706 const int m_numDynamicOffsets;
1707 const deUint32* const m_dynamicOffsets;
1708 const int m_numPreBarriers;
1709 const vk::VkBufferMemoryBarrier* const m_preBarriers;
1710 const int m_numPostBarriers;
1711 const vk::VkBufferMemoryBarrier* const m_postBarriers;
1712 };
1713
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)1714 ComputeCommand::ComputeCommand (const vk::DeviceInterface& vki,
1715 vk::VkDevice device,
1716 vk::VkPipeline pipeline,
1717 vk::VkPipelineLayout pipelineLayout,
1718 const tcu::UVec3& numWorkGroups,
1719 int numDescriptorSets,
1720 const vk::VkDescriptorSet* descriptorSets,
1721 int numDynamicOffsets,
1722 const deUint32* dynamicOffsets,
1723 int numPreBarriers,
1724 const vk::VkBufferMemoryBarrier* preBarriers,
1725 int numPostBarriers,
1726 const vk::VkBufferMemoryBarrier* postBarriers)
1727 : m_vki (vki)
1728 , m_device (device)
1729 , m_pipeline (pipeline)
1730 , m_pipelineLayout (pipelineLayout)
1731 , m_numWorkGroups (numWorkGroups)
1732 , m_numDescriptorSets (numDescriptorSets)
1733 , m_descriptorSets (descriptorSets)
1734 , m_numDynamicOffsets (numDynamicOffsets)
1735 , m_dynamicOffsets (dynamicOffsets)
1736 , m_numPreBarriers (numPreBarriers)
1737 , m_preBarriers (preBarriers)
1738 , m_numPostBarriers (numPostBarriers)
1739 , m_postBarriers (postBarriers)
1740 {
1741 }
1742
submitAndWait(deUint32 queueFamilyIndex,vk::VkQueue queue) const1743 void ComputeCommand::submitAndWait (deUint32 queueFamilyIndex, vk::VkQueue queue) const
1744 {
1745 const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo =
1746 {
1747 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
1748 DE_NULL,
1749 vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
1750 queueFamilyIndex, // queueFamilyIndex
1751 };
1752 const vk::Unique<vk::VkCommandPool> cmdPool (vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
1753
1754 const vk::VkFenceCreateInfo fenceCreateInfo =
1755 {
1756 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1757 DE_NULL,
1758 0u, // flags
1759 };
1760
1761 const vk::VkCommandBufferAllocateInfo cmdBufCreateInfo =
1762 {
1763 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
1764 DE_NULL,
1765 *cmdPool, // cmdPool
1766 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
1767 1u, // count
1768 };
1769 const vk::VkCommandBufferBeginInfo cmdBufBeginInfo =
1770 {
1771 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1772 DE_NULL,
1773 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags
1774 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
1775 };
1776
1777 const vk::Unique<vk::VkFence> cmdCompleteFence (vk::createFence(m_vki, m_device, &fenceCreateInfo));
1778 const vk::Unique<vk::VkCommandBuffer> cmd (vk::allocateCommandBuffer(m_vki, m_device, &cmdBufCreateInfo));
1779 const deUint64 infiniteTimeout = ~(deUint64)0u;
1780
1781 VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
1782
1783 m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
1784 m_vki.cmdBindDescriptorSets(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, 0, m_numDescriptorSets, m_descriptorSets, m_numDynamicOffsets, m_dynamicOffsets);
1785
1786 if (m_numPreBarriers)
1787 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (vk::VkDependencyFlags)0,
1788 0, (const vk::VkMemoryBarrier*)DE_NULL,
1789 m_numPreBarriers, m_preBarriers,
1790 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
1791
1792 m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
1793 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
1794 0, (const vk::VkMemoryBarrier*)DE_NULL,
1795 m_numPostBarriers, m_postBarriers,
1796 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
1797 VK_CHECK(m_vki.endCommandBuffer(*cmd));
1798
1799 // run
1800 {
1801 const vk::VkSubmitInfo submitInfo =
1802 {
1803 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1804 DE_NULL,
1805 0u,
1806 (const vk::VkSemaphore*)0,
1807 (const vk::VkPipelineStageFlags*)DE_NULL,
1808 1u,
1809 &cmd.get(),
1810 0u,
1811 (const vk::VkSemaphore*)0,
1812 };
1813 VK_CHECK(m_vki.queueSubmit(queue, 1, &submitInfo, *cmdCompleteFence));
1814 }
1815 VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
1816 }
1817
1818 class BufferComputeInstance : public vkt::TestInstance
1819 {
1820 public:
1821 BufferComputeInstance (Context& context,
1822 vk::VkDescriptorType descriptorType,
1823 ShaderInputInterface shaderInterface,
1824 bool viewOffset,
1825 bool dynamicOffset,
1826 bool dynamicOffsetNonZero);
1827
1828 private:
1829 vk::Move<vk::VkBuffer> createColorDataBuffer (deUint32 offset, deUint32 bufferSize, const tcu::Vec4& value1, const tcu::Vec4& value2, de::MovePtr<vk::Allocation>* outAllocation);
1830 vk::Move<vk::VkBufferView> createBufferView (vk::VkBuffer buffer, deUint32 offset) const;
1831 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (void) const;
1832 vk::Move<vk::VkDescriptorPool> createDescriptorPool (void) const;
1833 vk::Move<vk::VkDescriptorSet> createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf) const;
1834
1835 tcu::TestStatus iterate (void);
1836 void logTestPlan (void) const;
1837 tcu::TestStatus testResourceAccess (void);
1838
1839 enum
1840 {
1841 STATIC_OFFSET_VALUE_A = 256,
1842 DYNAMIC_OFFSET_VALUE_A = 512,
1843 STATIC_OFFSET_VALUE_B = 1024,
1844 DYNAMIC_OFFSET_VALUE_B = 768,
1845 };
1846
1847 const vk::VkDescriptorType m_descriptorType;
1848 const ShaderInputInterface m_shaderInterface;
1849 const bool m_setViewOffset;
1850 const bool m_setDynamicOffset;
1851 const bool m_dynamicOffsetNonZero;
1852
1853 const vk::DeviceInterface& m_vki;
1854 const vk::VkDevice m_device;
1855 const vk::VkQueue m_queue;
1856 const deUint32 m_queueFamilyIndex;
1857 vk::Allocator& m_allocator;
1858
1859 const ComputeInstanceResultBuffer m_result;
1860 };
1861
BufferComputeInstance(Context & context,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,bool viewOffset,bool dynamicOffset,bool dynamicOffsetNonZero)1862 BufferComputeInstance::BufferComputeInstance (Context& context,
1863 vk::VkDescriptorType descriptorType,
1864 ShaderInputInterface shaderInterface,
1865 bool viewOffset,
1866 bool dynamicOffset,
1867 bool dynamicOffsetNonZero)
1868 : vkt::TestInstance (context)
1869 , m_descriptorType (descriptorType)
1870 , m_shaderInterface (shaderInterface)
1871 , m_setViewOffset (viewOffset)
1872 , m_setDynamicOffset (dynamicOffset)
1873 , m_dynamicOffsetNonZero (dynamicOffsetNonZero)
1874 , m_vki (context.getDeviceInterface())
1875 , m_device (context.getDevice())
1876 , m_queue (context.getUniversalQueue())
1877 , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
1878 , m_allocator (context.getDefaultAllocator())
1879 , m_result (m_vki, m_device, m_allocator)
1880 {
1881 if (m_dynamicOffsetNonZero)
1882 DE_ASSERT(m_setDynamicOffset);
1883 }
1884
createColorDataBuffer(deUint32 offset,deUint32 bufferSize,const tcu::Vec4 & value1,const tcu::Vec4 & value2,de::MovePtr<vk::Allocation> * outAllocation)1885 vk::Move<vk::VkBuffer> BufferComputeInstance::createColorDataBuffer (deUint32 offset, deUint32 bufferSize, const tcu::Vec4& value1, const tcu::Vec4& value2, de::MovePtr<vk::Allocation>* outAllocation)
1886 {
1887 DE_ASSERT(offset + sizeof(tcu::Vec4[2]) <= bufferSize);
1888
1889 const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType);
1890 const vk::VkBufferUsageFlags usageFlags = (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1891 const vk::VkBufferCreateInfo createInfo =
1892 {
1893 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1894 DE_NULL,
1895 0u, // flags
1896 (vk::VkDeviceSize)bufferSize, // size
1897 usageFlags, // usage
1898 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
1899 0u, // queueFamilyCount
1900 DE_NULL, // pQueueFamilyIndices
1901 };
1902 vk::Move<vk::VkBuffer> buffer (vk::createBuffer(m_vki, m_device, &createInfo));
1903 de::MovePtr<vk::Allocation> allocation (allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible));
1904 void* mapPtr = allocation->getHostPtr();
1905
1906 if (offset)
1907 deMemset(mapPtr, 0x5A, (size_t)offset);
1908 deMemcpy((deUint8*)mapPtr + offset, value1.getPtr(), sizeof(tcu::Vec4));
1909 deMemcpy((deUint8*)mapPtr + offset + sizeof(tcu::Vec4), value2.getPtr(), sizeof(tcu::Vec4));
1910 deMemset((deUint8*)mapPtr + offset + 2 * sizeof(tcu::Vec4), 0x5A, (size_t)bufferSize - (size_t)offset - 2 * sizeof(tcu::Vec4));
1911
1912 flushMappedMemoryRange(m_vki, m_device, allocation->getMemory(), allocation->getOffset(), bufferSize);
1913
1914 *outAllocation = allocation;
1915 return buffer;
1916 }
1917
createDescriptorSetLayout(void) const1918 vk::Move<vk::VkDescriptorSetLayout> BufferComputeInstance::createDescriptorSetLayout (void) const
1919 {
1920 vk::DescriptorSetLayoutBuilder builder;
1921
1922 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1923
1924 switch (m_shaderInterface)
1925 {
1926 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1927 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1928 break;
1929
1930 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1931 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1932 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1933 break;
1934
1935 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1936 builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1937 break;
1938
1939 default:
1940 DE_FATAL("Impossible");
1941 };
1942
1943 return builder.build(m_vki, m_device);
1944 }
1945
createDescriptorPool(void) const1946 vk::Move<vk::VkDescriptorPool> BufferComputeInstance::createDescriptorPool (void) const
1947 {
1948 return vk::DescriptorPoolBuilder()
1949 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1950 .addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
1951 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
1952 }
1953
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout,vk::VkBuffer viewA,deUint32 offsetA,vk::VkBuffer viewB,deUint32 offsetB,vk::VkBuffer resBuf) const1954 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) const
1955 {
1956 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
1957 const vk::VkDescriptorBufferInfo bufferInfos[2] =
1958 {
1959 vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
1960 vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
1961 };
1962 const vk::VkDescriptorSetAllocateInfo allocInfo =
1963 {
1964 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1965 DE_NULL,
1966 pool,
1967 1u,
1968 &layout
1969 };
1970
1971 vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
1972 vk::DescriptorSetUpdateBuilder builder;
1973
1974 // result
1975 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
1976
1977 // buffers
1978 switch (m_shaderInterface)
1979 {
1980 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1981 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &bufferInfos[0]);
1982 break;
1983
1984 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1985 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &bufferInfos[0]);
1986 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &bufferInfos[1]);
1987 break;
1988
1989 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1990 builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, bufferInfos);
1991 break;
1992
1993 default:
1994 DE_FATAL("Impossible");
1995 }
1996
1997 builder.update(m_vki, m_device);
1998 return descriptorSet;
1999 }
2000
iterate(void)2001 tcu::TestStatus BufferComputeInstance::iterate (void)
2002 {
2003 logTestPlan();
2004 return testResourceAccess();
2005 }
2006
logTestPlan(void) const2007 void BufferComputeInstance::logTestPlan (void) const
2008 {
2009 std::ostringstream msg;
2010
2011 msg << "Accessing resource in a compute program.\n"
2012 << "Single descriptor set. Descriptor set contains "
2013 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
2014 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
2015 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
2016 (const char*)DE_NULL)
2017 << " source descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType)
2018 << " and one destination VK_DESCRIPTOR_TYPE_STORAGE_BUFFER to store results to.\n"
2019 << "Source descriptor buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
2020
2021 if (isDynamicDescriptorType(m_descriptorType))
2022 {
2023 if (m_setDynamicOffset)
2024 {
2025 msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
2026 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
2027 }
2028 else
2029 {
2030 msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
2031 }
2032 }
2033
2034 msg << "Destination buffer is pre-initialized to -1.\n";
2035
2036 m_context.getTestContext().getLog()
2037 << tcu::TestLog::Message
2038 << msg.str()
2039 << tcu::TestLog::EndMessage;
2040 }
2041
testResourceAccess(void)2042 tcu::TestStatus BufferComputeInstance::testResourceAccess (void)
2043 {
2044 enum
2045 {
2046 ADDRESSABLE_SIZE = 256, // allocate a lot more than required
2047 };
2048
2049 const bool isDynamicCase = isDynamicDescriptorType(m_descriptorType);
2050 const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType);
2051 const deUint32 bindTimeOffsets[] =
2052 {
2053 (m_dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_A) : (0u),
2054 (m_dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_B) : (0u),
2055 };
2056
2057 const tcu::Vec4 colorA1 = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
2058 const tcu::Vec4 colorA2 = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
2059 const tcu::Vec4 colorB1 = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
2060 const tcu::Vec4 colorB2 = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
2061
2062 const deUint32 dataOffsetA = ((isDynamicCase) ? (bindTimeOffsets[0]) : 0) + ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u));
2063 const deUint32 dataOffsetB = ((isDynamicCase) ? (bindTimeOffsets[1]) : 0) + ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u));
2064 const deUint32 viewOffsetA = (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u);
2065 const deUint32 viewOffsetB = (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u);
2066 const deUint32 bufferSizeA = dataOffsetA + ADDRESSABLE_SIZE;
2067 const deUint32 bufferSizeB = dataOffsetB + ADDRESSABLE_SIZE;
2068
2069 de::MovePtr<vk::Allocation> bufferMemA;
2070 const vk::Unique<vk::VkBuffer> bufferA (createColorDataBuffer(dataOffsetA, bufferSizeA, colorA1, colorA2, &bufferMemA));
2071
2072 de::MovePtr<vk::Allocation> bufferMemB;
2073 const vk::Unique<vk::VkBuffer> bufferB ((getInterfaceNumResources(m_shaderInterface) == 1u)
2074 ? (vk::Move<vk::VkBuffer>())
2075 : (createColorDataBuffer(dataOffsetB, bufferSizeB, colorB1, colorB2, &bufferMemB)));
2076
2077 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout());
2078 const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool());
2079 const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout, *bufferA, viewOffsetA, *bufferB, viewOffsetB, m_result.getBuffer()));
2080 const ComputePipeline pipeline (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
2081
2082 const vk::VkAccessFlags inputBit = (isUniformBuffer) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
2083 const vk::VkBufferMemoryBarrier bufferBarriers[] =
2084 {
2085 {
2086 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2087 DE_NULL,
2088 vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask
2089 inputBit, // inputMask
2090 vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
2091 vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
2092 *bufferA, // buffer
2093 (vk::VkDeviceSize)0u, // offset
2094 (vk::VkDeviceSize)bufferSizeA, // size
2095 },
2096 {
2097 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2098 DE_NULL,
2099 vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask
2100 inputBit, // inputMask
2101 vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
2102 vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
2103 *bufferB, // buffer
2104 (vk::VkDeviceSize)0u, // offset
2105 (vk::VkDeviceSize)bufferSizeB, // size
2106 }
2107 };
2108
2109 const deUint32 numSrcBuffers = getInterfaceNumResources(m_shaderInterface);
2110
2111 const vk::VkDescriptorSet descriptorSets[] = { *descriptorSet };
2112 const int numDescriptorSets = DE_LENGTH_OF_ARRAY(descriptorSets);
2113 const deUint32* const dynamicOffsets = (m_setDynamicOffset) ? (bindTimeOffsets) : (DE_NULL);
2114 const deUint32 numDynamicOffsets = (m_setDynamicOffset) ? (numSrcBuffers) : (0);
2115 const vk::VkBufferMemoryBarrier* const preBarriers = bufferBarriers;
2116 const int numPreBarriers = numSrcBuffers;
2117 const vk::VkBufferMemoryBarrier* const postBarriers = m_result.getResultReadBarrier();
2118 const int numPostBarriers = 1;
2119
2120 const ComputeCommand compute (m_vki,
2121 m_device,
2122 pipeline.getPipeline(),
2123 pipeline.getPipelineLayout(),
2124 tcu::UVec3(4, 1, 1),
2125 numDescriptorSets, descriptorSets,
2126 numDynamicOffsets, dynamicOffsets,
2127 numPreBarriers, preBarriers,
2128 numPostBarriers, postBarriers);
2129
2130 const tcu::Vec4 refQuadrantValue14 = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (colorA2) :
2131 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? (colorB2) :
2132 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? (colorB2) :
2133 (tcu::Vec4(-2.0f));
2134 const tcu::Vec4 refQuadrantValue23 = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (colorA1) :
2135 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? (colorA1) :
2136 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? (colorA1) :
2137 (tcu::Vec4(-2.0f));
2138 const tcu::Vec4 references[4] =
2139 {
2140 refQuadrantValue14,
2141 refQuadrantValue23,
2142 refQuadrantValue23,
2143 refQuadrantValue14,
2144 };
2145 tcu::Vec4 results[4];
2146
2147 compute.submitAndWait(m_queueFamilyIndex, m_queue);
2148 m_result.readResultContentsTo(&results);
2149
2150 // verify
2151 if (results[0] == references[0] &&
2152 results[1] == references[1] &&
2153 results[2] == references[2] &&
2154 results[3] == references[3])
2155 {
2156 return tcu::TestStatus::pass("Pass");
2157 }
2158 else if (results[0] == tcu::Vec4(-1.0f) &&
2159 results[1] == tcu::Vec4(-1.0f) &&
2160 results[2] == tcu::Vec4(-1.0f) &&
2161 results[3] == tcu::Vec4(-1.0f))
2162 {
2163 m_context.getTestContext().getLog()
2164 << tcu::TestLog::Message
2165 << "Result buffer was not written to."
2166 << tcu::TestLog::EndMessage;
2167 return tcu::TestStatus::fail("Result buffer was not written to");
2168 }
2169 else
2170 {
2171 m_context.getTestContext().getLog()
2172 << tcu::TestLog::Message
2173 << "Error expected ["
2174 << references[0] << ", "
2175 << references[1] << ", "
2176 << references[2] << ", "
2177 << references[3] << "], got ["
2178 << results[0] << ", "
2179 << results[1] << ", "
2180 << results[2] << ", "
2181 << results[3] << "]"
2182 << tcu::TestLog::EndMessage;
2183 return tcu::TestStatus::fail("Invalid result values");
2184 }
2185 }
2186
2187 class QuadrantRendederCase : public vkt::TestCase
2188 {
2189 public:
2190 QuadrantRendederCase (tcu::TestContext& testCtx,
2191 const char* name,
2192 const char* description,
2193 glu::GLSLVersion glslVersion,
2194 vk::VkShaderStageFlags exitingStages,
2195 vk::VkShaderStageFlags activeStages);
2196 private:
2197 virtual std::string genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const = 0;
2198 virtual std::string genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const = 0;
2199 virtual std::string genResourceAccessSource (vk::VkShaderStageFlagBits stage) const = 0;
2200 virtual std::string genNoAccessSource (void) const = 0;
2201
2202 std::string genVertexSource (void) const;
2203 std::string genTessCtrlSource (void) const;
2204 std::string genTessEvalSource (void) const;
2205 std::string genGeometrySource (void) const;
2206 std::string genFragmentSource (void) const;
2207 std::string genComputeSource (void) const;
2208
2209 void initPrograms (vk::SourceCollections& programCollection) const;
2210
2211 protected:
2212 const glu::GLSLVersion m_glslVersion;
2213 const vk::VkShaderStageFlags m_exitingStages;
2214 const vk::VkShaderStageFlags m_activeStages;
2215 };
2216
QuadrantRendederCase(tcu::TestContext & testCtx,const char * name,const char * description,glu::GLSLVersion glslVersion,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages)2217 QuadrantRendederCase::QuadrantRendederCase (tcu::TestContext& testCtx,
2218 const char* name,
2219 const char* description,
2220 glu::GLSLVersion glslVersion,
2221 vk::VkShaderStageFlags exitingStages,
2222 vk::VkShaderStageFlags activeStages)
2223 : vkt::TestCase (testCtx, name, description)
2224 , m_glslVersion (glslVersion)
2225 , m_exitingStages (exitingStages)
2226 , m_activeStages (activeStages)
2227 {
2228 DE_ASSERT((m_exitingStages & m_activeStages) == m_activeStages);
2229 }
2230
genVertexSource(void) const2231 std::string QuadrantRendederCase::genVertexSource (void) const
2232 {
2233 const char* const nextStageName = ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u) ? ("tsc")
2234 : ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u) ? ("geo")
2235 : ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u) ? ("frag")
2236 : (DE_NULL);
2237 const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
2238 std::ostringstream buf;
2239
2240 if ((m_activeStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
2241 {
2242 const bool onlyVS = (m_activeStages == vk::VK_SHADER_STAGE_VERTEX_BIT);
2243
2244 // active vertex shader
2245 buf << versionDecl << "\n"
2246 << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT)
2247 << genResourceDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT, 0)
2248 << "layout(location = 0) out highp vec4 " << nextStageName << "_color;\n"
2249 << (onlyVS ? "" : "layout(location = 1) flat out highp int " + de::toString(nextStageName) + "_quadrant_id;\n")
2250 << "void main (void)\n"
2251 << "{\n"
2252 << " highp vec4 result_position;\n"
2253 << " highp int quadrant_id;\n"
2254 << s_quadrantGenVertexPosSource
2255 << " gl_Position = result_position;\n"
2256 << (onlyVS ? "" : "\t" + de::toString(nextStageName) + "_quadrant_id = quadrant_id;\n")
2257 << "\n"
2258 << " highp vec4 result_color;\n"
2259 << genResourceAccessSource(vk::VK_SHADER_STAGE_VERTEX_BIT)
2260 << " " << nextStageName << "_color = result_color;\n"
2261 << "}\n";
2262 }
2263 else
2264 {
2265 // do nothing
2266 buf << versionDecl << "\n"
2267 << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT)
2268 << "layout(location = 1) flat out highp int " << nextStageName << "_quadrant_id;\n"
2269 << "void main (void)\n"
2270 << "{\n"
2271 << " highp vec4 result_position;\n"
2272 << " highp int quadrant_id;\n"
2273 << s_quadrantGenVertexPosSource
2274 << " gl_Position = result_position;\n"
2275 << " " << nextStageName << "_quadrant_id = quadrant_id;\n"
2276 << "}\n";
2277 }
2278
2279 return buf.str();
2280 }
2281
genTessCtrlSource(void) const2282 std::string QuadrantRendederCase::genTessCtrlSource (void) const
2283 {
2284 const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
2285 const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
2286 const char* const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
2287 std::ostringstream buf;
2288
2289 if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
2290 {
2291 // contributing not implemented
2292 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
2293
2294 // active tc shader
2295 buf << versionDecl << "\n"
2296 << tessExtDecl
2297 << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
2298 << "layout(vertices=3) out;\n"
2299 << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0)
2300 << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
2301 << "layout(location = 0) out highp vec4 tes_color[];\n"
2302 << "void main (void)\n"
2303 << "{\n"
2304 << " highp vec4 result_color;\n"
2305 << " highp int quadrant_id = tsc_quadrant_id[gl_InvocationID];\n"
2306 << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
2307 << "\n"
2308 << " tes_color[gl_InvocationID] = result_color;\n"
2309 << "\n"
2310 << " // no dynamic input block indexing\n"
2311 << " highp vec4 position;\n"
2312 << " if (gl_InvocationID == 0)\n"
2313 << " position = gl_in[0].gl_Position;\n"
2314 << " else if (gl_InvocationID == 1)\n"
2315 << " position = gl_in[1].gl_Position;\n"
2316 << " else\n"
2317 << " position = gl_in[2].gl_Position;\n"
2318 << " gl_out[gl_InvocationID].gl_Position = position;\n"
2319 << " gl_TessLevelInner[0] = 2.8;\n"
2320 << " gl_TessLevelInner[1] = 2.8;\n"
2321 << " gl_TessLevelOuter[0] = 2.8;\n"
2322 << " gl_TessLevelOuter[1] = 2.8;\n"
2323 << " gl_TessLevelOuter[2] = 2.8;\n"
2324 << " gl_TessLevelOuter[3] = 2.8;\n"
2325 << "}\n";
2326 }
2327 else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
2328 {
2329 // active te shader, tc passthru
2330 buf << versionDecl << "\n"
2331 << tessExtDecl
2332 << "layout(vertices=3) out;\n"
2333 << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
2334 << "layout(location = 1) flat out highp int tes_quadrant_id[];\n"
2335 << "void main (void)\n"
2336 << "{\n"
2337 << " tes_quadrant_id[gl_InvocationID] = tsc_quadrant_id[0];\n"
2338 << "\n"
2339 << " // no dynamic input block indexing\n"
2340 << " highp vec4 position;\n"
2341 << " if (gl_InvocationID == 0)\n"
2342 << " position = gl_in[0].gl_Position;\n"
2343 << " else if (gl_InvocationID == 1)\n"
2344 << " position = gl_in[1].gl_Position;\n"
2345 << " else\n"
2346 << " position = gl_in[2].gl_Position;\n"
2347 << " gl_out[gl_InvocationID].gl_Position = position;\n"
2348 << " gl_TessLevelInner[0] = 2.8;\n"
2349 << " gl_TessLevelInner[1] = 2.8;\n"
2350 << " gl_TessLevelOuter[0] = 2.8;\n"
2351 << " gl_TessLevelOuter[1] = 2.8;\n"
2352 << " gl_TessLevelOuter[2] = 2.8;\n"
2353 << " gl_TessLevelOuter[3] = 2.8;\n"
2354 << "}\n";
2355 }
2356 else
2357 {
2358 // passthrough not implemented
2359 DE_FATAL("not implemented");
2360 }
2361
2362 return buf.str();
2363 }
2364
genTessEvalSource(void) const2365 std::string QuadrantRendederCase::genTessEvalSource (void) const
2366 {
2367 const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
2368 const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
2369 const char* const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
2370 std::ostringstream buf;
2371
2372 if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
2373 {
2374 // contributing not implemented
2375 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
2376
2377 // active te shader
2378 buf << versionDecl << "\n"
2379 << tessExtDecl
2380 << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
2381 << "layout(triangles) in;\n"
2382 << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 0)
2383 << "layout(location = 1) flat in highp int tes_quadrant_id[];\n"
2384 << "layout(location = 0) out highp vec4 frag_color;\n"
2385 << "void main (void)\n"
2386 << "{\n"
2387 << " highp vec4 result_color;\n"
2388 << " highp int quadrant_id = tes_quadrant_id[0];\n"
2389 << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
2390 << "\n"
2391 << " frag_color = result_color;\n"
2392 << " 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"
2393 << "}\n";
2394 }
2395 else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
2396 {
2397 // contributing not implemented
2398 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
2399
2400 // active tc shader, te is passthru
2401 buf << versionDecl << "\n"
2402 << tessExtDecl
2403 << "layout(triangles) in;\n"
2404 << "layout(location = 0) in highp vec4 tes_color[];\n"
2405 << "layout(location = 0) out highp vec4 frag_color;\n"
2406 << "void main (void)\n"
2407 << "{\n"
2408 << " frag_color = tes_color[0];\n"
2409 << " 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"
2410 << "}\n";
2411 }
2412 else
2413 {
2414 // passthrough not implemented
2415 DE_FATAL("not implemented");
2416 }
2417
2418 return buf.str();
2419 }
2420
genGeometrySource(void) const2421 std::string QuadrantRendederCase::genGeometrySource (void) const
2422 {
2423 const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
2424 const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
2425 const char* const geomExtDecl = extRequired ? "#extension GL_EXT_geometry_shader : require\n" : "";
2426 std::ostringstream buf;
2427
2428 if ((m_activeStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
2429 {
2430 // contributing not implemented
2431 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_GEOMETRY_BIT);
2432
2433 // active geometry shader
2434 buf << versionDecl << "\n"
2435 << geomExtDecl
2436 << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
2437 << "layout(triangles) in;\n"
2438 << "layout(triangle_strip, max_vertices=4) out;\n"
2439 << genResourceDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT, 0)
2440 << "layout(location = 1) flat in highp int geo_quadrant_id[];\n"
2441 << "layout(location = 0) out highp vec4 frag_color;\n"
2442 << "void main (void)\n"
2443 << "{\n"
2444 << " highp int quadrant_id;\n"
2445 << " highp vec4 result_color;\n"
2446 << "\n"
2447 << " quadrant_id = geo_quadrant_id[0];\n"
2448 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
2449 << " frag_color = result_color;\n"
2450 << " gl_Position = gl_in[0].gl_Position;\n"
2451 << " EmitVertex();\n"
2452 << "\n"
2453 << " quadrant_id = geo_quadrant_id[1];\n"
2454 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
2455 << " frag_color = result_color;\n"
2456 << " gl_Position = gl_in[1].gl_Position;\n"
2457 << " EmitVertex();\n"
2458 << "\n"
2459 << " quadrant_id = geo_quadrant_id[2];\n"
2460 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
2461 << " frag_color = result_color;\n"
2462 << " gl_Position = gl_in[0].gl_Position * 0.5 + gl_in[2].gl_Position * 0.5;\n"
2463 << " EmitVertex();\n"
2464 << "\n"
2465 << " quadrant_id = geo_quadrant_id[0];\n"
2466 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
2467 << " frag_color = result_color;\n"
2468 << " gl_Position = gl_in[2].gl_Position;\n"
2469 << " EmitVertex();\n"
2470 << "}\n";
2471 }
2472 else
2473 {
2474 // passthrough not implemented
2475 DE_FATAL("not implemented");
2476 }
2477
2478 return buf.str();
2479 }
2480
genFragmentSource(void) const2481 std::string QuadrantRendederCase::genFragmentSource (void) const
2482 {
2483 const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
2484 std::ostringstream buf;
2485
2486 if ((m_activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
2487 {
2488 buf << versionDecl << "\n"
2489 << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
2490 << genResourceDeclarations(vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0);
2491
2492 if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
2493 {
2494 // there are other stages, this is just a contributor
2495 buf << "layout(location = 0) in mediump vec4 frag_color;\n";
2496 }
2497
2498 buf << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
2499 << "layout(location = 0) out mediump vec4 o_color;\n"
2500 << "void main (void)\n"
2501 << "{\n"
2502 << " highp int quadrant_id = frag_quadrant_id;\n"
2503 << " highp vec4 result_color;\n"
2504 << genResourceAccessSource(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
2505
2506 if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
2507 {
2508 // just contributor
2509 buf << " if (frag_quadrant_id < 2)\n"
2510 << " o_color = result_color;\n"
2511 << " else\n"
2512 << " o_color = frag_color;\n";
2513 }
2514 else
2515 buf << " o_color = result_color;\n";
2516
2517 buf << "}\n";
2518 }
2519 else if (m_activeStages == 0u)
2520 {
2521 // special case, no active stages
2522 buf << versionDecl << "\n"
2523 << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
2524 << "layout(location = 0) out mediump vec4 o_color;\n"
2525 << "void main (void)\n"
2526 << "{\n"
2527 << " highp int quadrant_id = frag_quadrant_id;\n"
2528 << " highp vec4 result_color;\n"
2529 << genNoAccessSource()
2530 << " o_color = result_color;\n"
2531 << "}\n";
2532 }
2533 else
2534 {
2535 // passthrough
2536 buf << versionDecl << "\n"
2537 << "layout(location = 0) in mediump vec4 frag_color;\n"
2538 "layout(location = 0) out mediump vec4 o_color;\n"
2539 "void main (void)\n"
2540 "{\n"
2541 " o_color = frag_color;\n"
2542 "}\n";
2543 }
2544
2545 return buf.str();
2546 }
2547
genComputeSource(void) const2548 std::string QuadrantRendederCase::genComputeSource (void) const
2549 {
2550 const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
2551 std::ostringstream buf;
2552
2553 buf << versionDecl << "\n"
2554 << genExtensionDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT)
2555 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2556 << genResourceDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT, 1)
2557 << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
2558 << "{\n"
2559 << " highp vec4 read_colors[4];\n"
2560 << "} b_out;\n"
2561 << "void main (void)\n"
2562 << "{\n"
2563 << " highp int quadrant_id = int(gl_WorkGroupID.x);\n"
2564 << " highp vec4 result_color;\n"
2565 << genResourceAccessSource(vk::VK_SHADER_STAGE_COMPUTE_BIT)
2566 << " b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
2567 << "}\n";
2568
2569 return buf.str();
2570 }
2571
initPrograms(vk::SourceCollections & programCollection) const2572 void QuadrantRendederCase::initPrograms (vk::SourceCollections& programCollection) const
2573 {
2574 if ((m_exitingStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
2575 programCollection.glslSources.add("vertex") << glu::VertexSource(genVertexSource());
2576
2577 if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
2578 programCollection.glslSources.add("tess_ctrl") << glu::TessellationControlSource(genTessCtrlSource());
2579
2580 if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
2581 programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(genTessEvalSource());
2582
2583 if ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
2584 programCollection.glslSources.add("geometry") << glu::GeometrySource(genGeometrySource());
2585
2586 if ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
2587 programCollection.glslSources.add("fragment") << glu::FragmentSource(genFragmentSource());
2588
2589 if ((m_exitingStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) != 0u)
2590 programCollection.glslSources.add("compute") << glu::ComputeSource(genComputeSource());
2591 }
2592
2593 class BufferDescriptorCase : public QuadrantRendederCase
2594 {
2595 public:
2596 enum
2597 {
2598 FLAG_VIEW_OFFSET = (1u << 1u),
2599 FLAG_DYNAMIC_OFFSET_ZERO = (1u << 2u),
2600 FLAG_DYNAMIC_OFFSET_NONZERO = (1u << 3u),
2601 };
2602 // enum continues where resource flags ends
2603 DE_STATIC_ASSERT((deUint32)FLAG_VIEW_OFFSET == (deUint32)RESOURCE_FLAG_LAST);
2604
2605 BufferDescriptorCase (tcu::TestContext& testCtx,
2606 const char* name,
2607 const char* description,
2608 bool isPrimaryCmdBuf,
2609 vk::VkDescriptorType descriptorType,
2610 vk::VkShaderStageFlags exitingStages,
2611 vk::VkShaderStageFlags activeStages,
2612 ShaderInputInterface shaderInterface,
2613 deUint32 flags);
2614
2615 private:
2616 std::string genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const;
2617 std::string genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
2618 std::string genResourceAccessSource (vk::VkShaderStageFlagBits stage) const;
2619 std::string genNoAccessSource (void) const;
2620
2621 vkt::TestInstance* createInstance (vkt::Context& context) const;
2622
2623 const bool m_viewOffset;
2624 const bool m_dynamicOffsetSet;
2625 const bool m_dynamicOffsetNonZero;
2626 const bool m_isPrimaryCmdBuf;
2627 const vk::VkDescriptorType m_descriptorType;
2628 const ShaderInputInterface m_shaderInterface;
2629 };
2630
BufferDescriptorCase(tcu::TestContext & testCtx,const char * name,const char * description,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,ShaderInputInterface shaderInterface,deUint32 flags)2631 BufferDescriptorCase::BufferDescriptorCase (tcu::TestContext& testCtx,
2632 const char* name,
2633 const char* description,
2634 bool isPrimaryCmdBuf,
2635 vk::VkDescriptorType descriptorType,
2636 vk::VkShaderStageFlags exitingStages,
2637 vk::VkShaderStageFlags activeStages,
2638 ShaderInputInterface shaderInterface,
2639 deUint32 flags)
2640 : QuadrantRendederCase (testCtx, name, description, glu::GLSL_VERSION_310_ES, exitingStages, activeStages)
2641 , m_viewOffset ((flags & FLAG_VIEW_OFFSET) != 0u)
2642 , m_dynamicOffsetSet ((flags & (FLAG_DYNAMIC_OFFSET_ZERO | FLAG_DYNAMIC_OFFSET_NONZERO)) != 0u)
2643 , m_dynamicOffsetNonZero ((flags & FLAG_DYNAMIC_OFFSET_NONZERO) != 0u)
2644 , m_isPrimaryCmdBuf (isPrimaryCmdBuf)
2645 , m_descriptorType (descriptorType)
2646 , m_shaderInterface (shaderInterface)
2647 {
2648 }
2649
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const2650 std::string BufferDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const
2651 {
2652 DE_UNREF(stage);
2653 return "";
2654 }
2655
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const2656 std::string BufferDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const
2657 {
2658 DE_UNREF(stage);
2659
2660 const bool isUniform = isUniformDescriptorType(m_descriptorType);
2661 const char* const storageType = (isUniform) ? ("uniform") : ("buffer");
2662 std::ostringstream buf;
2663
2664 switch (m_shaderInterface)
2665 {
2666 case SHADER_INPUT_SINGLE_DESCRIPTOR:
2667 buf << "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferName\n"
2668 << "{\n"
2669 << " highp vec4 colorA;\n"
2670 << " highp vec4 colorB;\n"
2671 << "} b_instance;\n";
2672 break;
2673
2674 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2675 buf << "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferNameA\n"
2676 << "{\n"
2677 << " highp vec4 colorA;\n"
2678 << " highp vec4 colorB;\n"
2679 << "} b_instanceA;\n"
2680 << "layout(set = 0, binding = " << (numUsedBindings+1) << ", std140) " << storageType << " BufferNameB\n"
2681 << "{\n"
2682 << " highp vec4 colorA;\n"
2683 << " highp vec4 colorB;\n"
2684 << "} b_instanceB;\n";
2685 break;
2686
2687 case SHADER_INPUT_DESCRIPTOR_ARRAY:
2688 buf << "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferName\n"
2689 << "{\n"
2690 << " highp vec4 colorA;\n"
2691 << " highp vec4 colorB;\n"
2692 << "} b_instances[2];\n";
2693 break;
2694
2695 default:
2696 DE_FATAL("Impossible");
2697 }
2698
2699 return buf.str();
2700 }
2701
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const2702 std::string BufferDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const
2703 {
2704 DE_UNREF(stage);
2705
2706 std::ostringstream buf;
2707
2708 switch (m_shaderInterface)
2709 {
2710 case SHADER_INPUT_SINGLE_DESCRIPTOR:
2711 buf << " if (quadrant_id == 1 || quadrant_id == 2)\n"
2712 << " result_color = b_instance.colorA;\n"
2713 << " else\n"
2714 << " result_color = b_instance.colorB;\n";
2715 break;
2716
2717 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2718 buf << " if (quadrant_id == 1 || quadrant_id == 2)\n"
2719 << " result_color = b_instanceA.colorA;\n"
2720 << " else\n"
2721 << " result_color = b_instanceB.colorB;\n";
2722 break;
2723
2724 case SHADER_INPUT_DESCRIPTOR_ARRAY:
2725 buf << " if (quadrant_id == 1 || quadrant_id == 2)\n"
2726 << " result_color = b_instances[0].colorA;\n"
2727 << " else\n"
2728 << " result_color = b_instances[1].colorB;\n";
2729 break;
2730
2731 default:
2732 DE_FATAL("Impossible");
2733 }
2734
2735 return buf.str();
2736 }
2737
genNoAccessSource(void) const2738 std::string BufferDescriptorCase::genNoAccessSource (void) const
2739 {
2740 return " if (quadrant_id == 1 || quadrant_id == 2)\n"
2741 " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
2742 " else\n"
2743 " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
2744 }
2745
createInstance(vkt::Context & context) const2746 vkt::TestInstance* BufferDescriptorCase::createInstance (vkt::Context& context) const
2747 {
2748 verifyDriverSupport(context.getDeviceFeatures(), m_descriptorType, m_activeStages);
2749
2750 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
2751 {
2752 DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
2753 return new BufferComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero);
2754 }
2755 else
2756 return new BufferRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero);
2757 }
2758
2759 class ImageInstanceImages
2760 {
2761 public:
2762 ImageInstanceImages (const vk::DeviceInterface& vki,
2763 vk::VkDevice device,
2764 deUint32 queueFamilyIndex,
2765 vk::VkQueue queue,
2766 vk::Allocator& allocator,
2767 vk::VkDescriptorType descriptorType,
2768 vk::VkImageViewType viewType,
2769 int numImages,
2770 deUint32 baseMipLevel,
2771 deUint32 baseArraySlice);
2772
2773 private:
2774 static vk::Move<vk::VkImage> createImage (const vk::DeviceInterface& vki,
2775 vk::VkDevice device,
2776 vk::Allocator& allocator,
2777 vk::VkDescriptorType descriptorType,
2778 vk::VkImageViewType viewType,
2779 const tcu::TextureLevelPyramid& sourceImage,
2780 de::MovePtr<vk::Allocation>* outAllocation);
2781
2782 static vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface& vki,
2783 vk::VkDevice device,
2784 vk::VkImageViewType viewType,
2785 const tcu::TextureLevelPyramid& sourceImage,
2786 vk::VkImage image,
2787 deUint32 baseMipLevel,
2788 deUint32 baseArraySlice);
2789
2790 void populateSourceImage (tcu::TextureLevelPyramid* dst,
2791 bool isFirst) const;
2792
2793 void uploadImage (const vk::DeviceInterface& vki,
2794 vk::VkDevice device,
2795 deUint32 queueFamilyIndex,
2796 vk::VkQueue queue,
2797 vk::Allocator& allocator,
2798 vk::VkImage image,
2799 vk::VkImageLayout layout,
2800 const tcu::TextureLevelPyramid& data);
2801
2802 protected:
2803 enum
2804 {
2805 IMAGE_SIZE = 64,
2806 NUM_MIP_LEVELS = 2,
2807 ARRAY_SIZE = 2,
2808 };
2809
2810 const vk::VkImageViewType m_viewType;
2811 const deUint32 m_baseMipLevel;
2812 const deUint32 m_baseArraySlice;
2813
2814 const tcu::TextureFormat m_imageFormat;
2815 tcu::TextureLevelPyramid m_sourceImageA;
2816 tcu::TextureLevelPyramid m_sourceImageB;
2817
2818 de::MovePtr<vk::Allocation> m_imageMemoryA;
2819 de::MovePtr<vk::Allocation> m_imageMemoryB;
2820 vk::Move<vk::VkImage> m_imageA;
2821 vk::Move<vk::VkImage> m_imageB;
2822 vk::Move<vk::VkImageView> m_imageViewA;
2823 vk::Move<vk::VkImageView> m_imageViewB;
2824 };
2825
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)2826 ImageInstanceImages::ImageInstanceImages (const vk::DeviceInterface& vki,
2827 vk::VkDevice device,
2828 deUint32 queueFamilyIndex,
2829 vk::VkQueue queue,
2830 vk::Allocator& allocator,
2831 vk::VkDescriptorType descriptorType,
2832 vk::VkImageViewType viewType,
2833 int numImages,
2834 deUint32 baseMipLevel,
2835 deUint32 baseArraySlice)
2836 : m_viewType (viewType)
2837 , m_baseMipLevel (baseMipLevel)
2838 , m_baseArraySlice (baseArraySlice)
2839 , m_imageFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
2840 , m_sourceImageA (m_imageFormat, NUM_MIP_LEVELS)
2841 , m_sourceImageB (m_imageFormat, NUM_MIP_LEVELS)
2842 , m_imageMemoryA (DE_NULL)
2843 , m_imageMemoryB (DE_NULL)
2844 , m_imageA (vk::Move<vk::VkImage>())
2845 , m_imageB (vk::Move<vk::VkImage>())
2846 , m_imageViewA (vk::Move<vk::VkImageView>())
2847 , m_imageViewB (vk::Move<vk::VkImageView>())
2848 {
2849 const vk::VkImageLayout layout = getImageLayoutForDescriptorType(descriptorType);
2850
2851 DE_ASSERT(numImages == 1 || numImages == 2);
2852
2853 populateSourceImage(&m_sourceImageA, true);
2854 m_imageA = createImage(vki, device, allocator, descriptorType, viewType, m_sourceImageA, &m_imageMemoryA);
2855 m_imageViewA = createImageView(vki, device, viewType, m_sourceImageA, *m_imageA, m_baseMipLevel, m_baseArraySlice);
2856 uploadImage(vki, device, queueFamilyIndex, queue, allocator, *m_imageA, layout, m_sourceImageA);
2857
2858 if (numImages == 2)
2859 {
2860 populateSourceImage(&m_sourceImageB, false);
2861 m_imageB = createImage(vki, device, allocator, descriptorType, viewType, m_sourceImageB, &m_imageMemoryB);
2862 m_imageViewB = createImageView(vki, device, viewType, m_sourceImageB, *m_imageB, m_baseMipLevel, m_baseArraySlice);
2863 uploadImage(vki, device, queueFamilyIndex, queue, allocator, *m_imageB, layout, m_sourceImageB);
2864 }
2865 }
2866
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)2867 vk::Move<vk::VkImage> ImageInstanceImages::createImage (const vk::DeviceInterface& vki,
2868 vk::VkDevice device,
2869 vk::Allocator& allocator,
2870 vk::VkDescriptorType descriptorType,
2871 vk::VkImageViewType viewType,
2872 const tcu::TextureLevelPyramid& sourceImage,
2873 de::MovePtr<vk::Allocation>* outAllocation)
2874 {
2875 const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0);
2876 const bool isCube = (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
2877 const bool isStorage = (descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
2878 const deUint32 readUsage = (isStorage) ? (vk::VK_IMAGE_USAGE_STORAGE_BIT) : (vk::VK_IMAGE_USAGE_SAMPLED_BIT);
2879 const deUint32 arraySize = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (baseLevel.getHeight())
2880 : (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (baseLevel.getDepth())
2881 : (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1)
2882 : (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (baseLevel.getDepth()) // cube: numFaces * numLayers
2883 : (0);
2884 const vk::VkExtent3D extent =
2885 {
2886 // x
2887 (deUint32)baseLevel.getWidth(),
2888
2889 // y
2890 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1u) : (deUint32)baseLevel.getHeight(),
2891
2892 // z
2893 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ((deUint32)baseLevel.getDepth()) : (1u),
2894 };
2895 const vk::VkImageCreateInfo createInfo =
2896 {
2897 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2898 DE_NULL,
2899 isCube ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (vk::VkImageCreateFlags)0,
2900 viewTypeToImageType(viewType), // imageType
2901 vk::mapTextureFormat(baseLevel.getFormat()), // format
2902 extent, // extent
2903 (deUint32)sourceImage.getNumLevels(), // mipLevels
2904 arraySize, // arraySize
2905 vk::VK_SAMPLE_COUNT_1_BIT, // samples
2906 vk::VK_IMAGE_TILING_OPTIMAL, // tiling
2907 readUsage | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT, // usage
2908 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
2909 0u, // queueFamilyCount
2910 DE_NULL, // pQueueFamilyIndices
2911 vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
2912 };
2913 vk::Move<vk::VkImage> image (vk::createImage(vki, device, &createInfo));
2914
2915 *outAllocation = allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any);
2916 return image;
2917 }
2918
createImageView(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkImageViewType viewType,const tcu::TextureLevelPyramid & sourceImage,vk::VkImage image,deUint32 baseMipLevel,deUint32 baseArraySlice)2919 vk::Move<vk::VkImageView> ImageInstanceImages::createImageView (const vk::DeviceInterface& vki,
2920 vk::VkDevice device,
2921 vk::VkImageViewType viewType,
2922 const tcu::TextureLevelPyramid& sourceImage,
2923 vk::VkImage image,
2924 deUint32 baseMipLevel,
2925 deUint32 baseArraySlice)
2926 {
2927 const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0);
2928 const deUint32 viewTypeBaseSlice = (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * baseArraySlice) : (baseArraySlice);
2929 const deUint32 viewArraySize = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D) ? (1)
2930 : (viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (baseLevel.getHeight() - viewTypeBaseSlice)
2931 : (viewType == vk::VK_IMAGE_VIEW_TYPE_2D) ? (1)
2932 : (viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (baseLevel.getDepth() - viewTypeBaseSlice)
2933 : (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1)
2934 : (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE) ? (6)
2935 : (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (baseLevel.getDepth() - viewTypeBaseSlice) // cube: numFaces * numLayers
2936 : (0);
2937
2938 DE_ASSERT(viewArraySize > 0);
2939
2940 const vk::VkImageSubresourceRange resourceRange =
2941 {
2942 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
2943 baseMipLevel, // baseMipLevel
2944 sourceImage.getNumLevels() - baseMipLevel, // mipLevels
2945 viewTypeBaseSlice, // baseArraySlice
2946 viewArraySize, // arraySize
2947 };
2948 const vk::VkImageViewCreateInfo createInfo =
2949 {
2950 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
2951 DE_NULL,
2952 (vk::VkImageViewCreateFlags)0,
2953 image, // image
2954 viewType, // viewType
2955 vk::mapTextureFormat(baseLevel.getFormat()), // format
2956 {
2957 vk::VK_COMPONENT_SWIZZLE_R,
2958 vk::VK_COMPONENT_SWIZZLE_G,
2959 vk::VK_COMPONENT_SWIZZLE_B,
2960 vk::VK_COMPONENT_SWIZZLE_A
2961 }, // channels
2962 resourceRange, // subresourceRange
2963 };
2964 return vk::createImageView(vki, device, &createInfo);
2965 }
2966
populateSourceImage(tcu::TextureLevelPyramid * dst,bool isFirst) const2967 void ImageInstanceImages::populateSourceImage (tcu::TextureLevelPyramid* dst, bool isFirst) const
2968 {
2969 const int numLevels = dst->getNumLevels();
2970
2971 for (int level = 0; level < numLevels; ++level)
2972 {
2973 const int width = IMAGE_SIZE >> level;
2974 const int height = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (ARRAY_SIZE)
2975 : (IMAGE_SIZE >> level);
2976 const int depth = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1)
2977 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (ARRAY_SIZE)
2978 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * ARRAY_SIZE)
2979 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (IMAGE_SIZE >> level)
2980 : (1);
2981
2982 dst->allocLevel(level, width, height, depth);
2983
2984 {
2985 const tcu::PixelBufferAccess levelAccess = dst->getLevel(level);
2986
2987 for (int z = 0; z < depth; ++z)
2988 for (int y = 0; y < height; ++y)
2989 for (int x = 0; x < width; ++x)
2990 {
2991 const int gradPos = x + y + z;
2992 const int gradMax = width + height + depth - 3;
2993
2994 const int red = 255 * gradPos / gradMax; //!< gradient from 0 -> max (detects large offset errors)
2995 const int green = ((gradPos % 2 == 0) ? (127) : (0)) + ((gradPos % 4 < 3) ? (128) : (0)); //!< 3-level M pattern (detects small offset errors)
2996 const int blue = (128 * level / numLevels) + (isFirst ? 127 : 0); //!< level and image index (detects incorrect lod / image)
2997
2998 DE_ASSERT(de::inRange(red, 0, 255));
2999 DE_ASSERT(de::inRange(green, 0, 255));
3000 DE_ASSERT(de::inRange(blue, 0, 255));
3001
3002 levelAccess.setPixel(tcu::IVec4(red, green, blue, 255), x, y, z);
3003 }
3004 }
3005 }
3006 }
3007
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)3008 void ImageInstanceImages::uploadImage (const vk::DeviceInterface& vki,
3009 vk::VkDevice device,
3010 deUint32 queueFamilyIndex,
3011 vk::VkQueue queue,
3012 vk::Allocator& allocator,
3013 vk::VkImage image,
3014 vk::VkImageLayout layout,
3015 const tcu::TextureLevelPyramid& data)
3016 {
3017 const deUint32 arraySize = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
3018 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * (deUint32)ARRAY_SIZE) :
3019 ((deUint32)ARRAY_SIZE);
3020 const deUint32 dataBufferSize = getTextureLevelPyramidDataSize(data);
3021 const vk::VkBufferCreateInfo bufferCreateInfo =
3022 {
3023 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
3024 DE_NULL,
3025 0u, // flags
3026 dataBufferSize, // size
3027 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
3028 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
3029 0u, // queueFamilyCount
3030 DE_NULL, // pQueueFamilyIndices
3031 };
3032 const vk::Unique<vk::VkBuffer> dataBuffer (vk::createBuffer(vki, device, &bufferCreateInfo));
3033 const de::MovePtr<vk::Allocation> dataBufferMemory = allocateAndBindObjectMemory(vki, device, allocator, *dataBuffer, vk::MemoryRequirement::HostVisible);
3034 const vk::VkFenceCreateInfo fenceCreateInfo =
3035 {
3036 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
3037 DE_NULL,
3038 0u, // flags
3039 };
3040 const vk::VkBufferMemoryBarrier preMemoryBarrier =
3041 {
3042 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
3043 DE_NULL,
3044 vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask
3045 vk::VK_ACCESS_TRANSFER_READ_BIT, // inputMask
3046 vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
3047 vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
3048 *dataBuffer, // buffer
3049 0u, // offset
3050 dataBufferSize, // size
3051 };
3052 const vk::VkImageSubresourceRange fullSubrange =
3053 {
3054 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
3055 0u, // baseMipLevel
3056 (deUint32)data.getNumLevels(), // mipLevels
3057 0u, // baseArraySlice
3058 arraySize, // arraySize
3059 };
3060 const vk::VkImageMemoryBarrier preImageBarrier =
3061 {
3062 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3063 DE_NULL,
3064 0u, // outputMask
3065 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // inputMask
3066 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
3067 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // newLayout
3068 vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
3069 vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
3070 image, // image
3071 fullSubrange // subresourceRange
3072 };
3073 const vk::VkImageMemoryBarrier postImageBarrier =
3074 {
3075 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3076 DE_NULL,
3077 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // outputMask
3078 vk::VK_ACCESS_SHADER_READ_BIT, // inputMask
3079 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // oldLayout
3080 layout, // newLayout
3081 vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
3082 vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
3083 image, // image
3084 fullSubrange // subresourceRange
3085 };
3086 const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo =
3087 {
3088 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
3089 DE_NULL,
3090 vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
3091 queueFamilyIndex, // queueFamilyIndex
3092 };
3093 const vk::Unique<vk::VkCommandPool> cmdPool (vk::createCommandPool(vki, device, &cmdPoolCreateInfo));
3094 const vk::VkCommandBufferAllocateInfo cmdBufCreateInfo =
3095 {
3096 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
3097 DE_NULL,
3098 *cmdPool, // cmdPool
3099 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
3100 1u, // count
3101 };
3102 const vk::VkCommandBufferBeginInfo cmdBufBeginInfo =
3103 {
3104 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
3105 DE_NULL,
3106 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags
3107 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
3108 };
3109
3110 const vk::Unique<vk::VkCommandBuffer> cmd (vk::allocateCommandBuffer(vki, device, &cmdBufCreateInfo));
3111 const vk::Unique<vk::VkFence> cmdCompleteFence (vk::createFence(vki, device, &fenceCreateInfo));
3112 const deUint64 infiniteTimeout = ~(deUint64)0u;
3113 std::vector<vk::VkBufferImageCopy> copySlices;
3114
3115 // copy data to buffer
3116 writeTextureLevelPyramidData(dataBufferMemory->getHostPtr(), dataBufferSize, data, m_viewType , ©Slices);
3117 flushMappedMemoryRange(vki, device, dataBufferMemory->getMemory(), dataBufferMemory->getOffset(), dataBufferSize);
3118
3119 // record command buffer
3120 VK_CHECK(vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
3121 vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0,
3122 0, (const vk::VkMemoryBarrier*)DE_NULL,
3123 1, &preMemoryBarrier,
3124 1, &preImageBarrier);
3125 vki.cmdCopyBufferToImage(*cmd, *dataBuffer, image, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copySlices.size(), ©Slices[0]);
3126 vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
3127 0, (const vk::VkMemoryBarrier*)DE_NULL,
3128 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
3129 1, &postImageBarrier);
3130 VK_CHECK(vki.endCommandBuffer(*cmd));
3131
3132 // submit and wait for command buffer to complete before killing it
3133 {
3134 const vk::VkSubmitInfo submitInfo =
3135 {
3136 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
3137 DE_NULL,
3138 0u,
3139 (const vk::VkSemaphore*)0,
3140 (const vk::VkPipelineStageFlags*)DE_NULL,
3141 1u,
3142 &cmd.get(),
3143 0u,
3144 (const vk::VkSemaphore*)0,
3145 };
3146 VK_CHECK(vki.queueSubmit(queue, 1, &submitInfo, *cmdCompleteFence));
3147 }
3148 VK_CHECK(vki.waitForFences(device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
3149 }
3150
3151 class ImageFetchInstanceImages : private ImageInstanceImages
3152 {
3153 public:
3154 ImageFetchInstanceImages (const vk::DeviceInterface& vki,
3155 vk::VkDevice device,
3156 deUint32 queueFamilyIndex,
3157 vk::VkQueue queue,
3158 vk::Allocator& allocator,
3159 vk::VkDescriptorType descriptorType,
3160 ShaderInputInterface shaderInterface,
3161 vk::VkImageViewType viewType,
3162 deUint32 baseMipLevel,
3163 deUint32 baseArraySlice);
3164
3165 static tcu::IVec3 getFetchPos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int fetchPosNdx);
3166 tcu::Vec4 fetchImageValue (int fetchPosNdx) const;
3167
getImageViewA(void) const3168 inline vk::VkImageView getImageViewA (void) const { return *m_imageViewA; }
getImageViewB(void) const3169 inline vk::VkImageView getImageViewB (void) const { return *m_imageViewB; }
3170
3171 private:
3172 enum
3173 {
3174 // some arbitrary sample points for all four quadrants
3175 SAMPLE_POINT_0_X = 6,
3176 SAMPLE_POINT_0_Y = 13,
3177 SAMPLE_POINT_0_Z = 49,
3178
3179 SAMPLE_POINT_1_X = 51,
3180 SAMPLE_POINT_1_Y = 40,
3181 SAMPLE_POINT_1_Z = 44,
3182
3183 SAMPLE_POINT_2_X = 42,
3184 SAMPLE_POINT_2_Y = 26,
3185 SAMPLE_POINT_2_Z = 19,
3186
3187 SAMPLE_POINT_3_X = 25,
3188 SAMPLE_POINT_3_Y = 25,
3189 SAMPLE_POINT_3_Z = 18,
3190 };
3191
3192 const ShaderInputInterface m_shaderInterface;
3193 };
3194
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)3195 ImageFetchInstanceImages::ImageFetchInstanceImages (const vk::DeviceInterface& vki,
3196 vk::VkDevice device,
3197 deUint32 queueFamilyIndex,
3198 vk::VkQueue queue,
3199 vk::Allocator& allocator,
3200 vk::VkDescriptorType descriptorType,
3201 ShaderInputInterface shaderInterface,
3202 vk::VkImageViewType viewType,
3203 deUint32 baseMipLevel,
3204 deUint32 baseArraySlice)
3205 : ImageInstanceImages (vki,
3206 device,
3207 queueFamilyIndex,
3208 queue,
3209 allocator,
3210 descriptorType,
3211 viewType,
3212 getInterfaceNumResources(shaderInterface), // numImages
3213 baseMipLevel,
3214 baseArraySlice)
3215 , m_shaderInterface (shaderInterface)
3216 {
3217 }
3218
isImageViewTypeArray(vk::VkImageViewType type)3219 bool isImageViewTypeArray (vk::VkImageViewType type)
3220 {
3221 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;
3222 }
3223
getFetchPos(vk::VkImageViewType viewType,deUint32 baseMipLevel,deUint32 baseArraySlice,int fetchPosNdx)3224 tcu::IVec3 ImageFetchInstanceImages::getFetchPos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int fetchPosNdx)
3225 {
3226 const tcu::IVec3 fetchPositions[4] =
3227 {
3228 tcu::IVec3(SAMPLE_POINT_0_X, SAMPLE_POINT_0_Y, SAMPLE_POINT_0_Z),
3229 tcu::IVec3(SAMPLE_POINT_1_X, SAMPLE_POINT_1_Y, SAMPLE_POINT_1_Z),
3230 tcu::IVec3(SAMPLE_POINT_2_X, SAMPLE_POINT_2_Y, SAMPLE_POINT_2_Z),
3231 tcu::IVec3(SAMPLE_POINT_3_X, SAMPLE_POINT_3_Y, SAMPLE_POINT_3_Z),
3232 };
3233 const tcu::IVec3 coord = de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
3234 const deUint32 imageSize = (deUint32)IMAGE_SIZE >> baseMipLevel;
3235 const deUint32 arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
3236
3237 switch (viewType)
3238 {
3239 case vk::VK_IMAGE_VIEW_TYPE_1D:
3240 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY: return tcu::IVec3(coord.x() % imageSize, coord.y() % arraySize, 0);
3241 case vk::VK_IMAGE_VIEW_TYPE_2D:
3242 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY: return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % arraySize);
3243 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
3244 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % (arraySize * 6));
3245 case vk::VK_IMAGE_VIEW_TYPE_3D: return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % imageSize);
3246 default:
3247 DE_FATAL("Impossible");
3248 return tcu::IVec3();
3249 }
3250 }
3251
fetchImageValue(int fetchPosNdx) const3252 tcu::Vec4 ImageFetchInstanceImages::fetchImageValue (int fetchPosNdx) const
3253 {
3254 DE_ASSERT(de::inBounds(fetchPosNdx, 0, 4));
3255
3256 const tcu::TextureLevelPyramid& fetchSrcA = m_sourceImageA;
3257 const tcu::TextureLevelPyramid& fetchSrcB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_sourceImageA) : (m_sourceImageB);
3258 const tcu::TextureLevelPyramid& fetchSrc = ((fetchPosNdx % 2) == 0) ? (fetchSrcA) : (fetchSrcB); // sampling order is ABAB
3259 tcu::IVec3 fetchPos = getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
3260
3261 // add base array layer into the appropriate coordinate, based on the view type
3262 if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
3263 fetchPos.z() += 6 * m_baseArraySlice;
3264 else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
3265 fetchPos.y() += m_baseArraySlice;
3266 else
3267 fetchPos.z() += m_baseArraySlice;
3268
3269 return fetchSrc.getLevel(m_baseMipLevel).getPixel(fetchPos.x(), fetchPos.y(), fetchPos.z());
3270 }
3271
3272 class ImageFetchRenderInstance : public SingleCmdRenderInstance
3273 {
3274 public:
3275 ImageFetchRenderInstance (vkt::Context& context,
3276 bool isPrimaryCmdBuf,
3277 vk::VkDescriptorType descriptorType,
3278 vk::VkShaderStageFlags stageFlags,
3279 ShaderInputInterface shaderInterface,
3280 vk::VkImageViewType viewType,
3281 deUint32 baseMipLevel,
3282 deUint32 baseArraySlice);
3283
3284 private:
3285 static vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vki,
3286 vk::VkDevice device,
3287 vk::VkDescriptorType descriptorType,
3288 ShaderInputInterface shaderInterface,
3289 vk::VkShaderStageFlags stageFlags);
3290
3291 static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki,
3292 vk::VkDevice device,
3293 vk::VkDescriptorSetLayout descriptorSetLayout);
3294
3295 static vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vki,
3296 vk::VkDevice device,
3297 vk::VkDescriptorType descriptorType,
3298 ShaderInputInterface shaderInterface);
3299
3300 static vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vki,
3301 vk::VkDevice device,
3302 vk::VkDescriptorType descriptorType,
3303 ShaderInputInterface shaderInterface,
3304 vk::VkDescriptorSetLayout layout,
3305 vk::VkDescriptorPool pool,
3306 vk::VkImageView viewA,
3307 vk::VkImageView viewB);
3308
3309 void logTestPlan (void) const;
3310 vk::VkPipelineLayout getPipelineLayout (void) const;
3311 void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const;
3312 tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const;
3313
3314 enum
3315 {
3316 RENDER_SIZE = 128,
3317 };
3318
3319 const vk::VkDescriptorType m_descriptorType;
3320 const vk::VkShaderStageFlags m_stageFlags;
3321 const ShaderInputInterface m_shaderInterface;
3322 const vk::VkImageViewType m_viewType;
3323 const deUint32 m_baseMipLevel;
3324 const deUint32 m_baseArraySlice;
3325
3326 const vk::Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
3327 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
3328 const ImageFetchInstanceImages m_images;
3329 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
3330 const vk::Unique<vk::VkDescriptorSet> m_descriptorSet;
3331 };
3332
ImageFetchRenderInstance(vkt::Context & context,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags stageFlags,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,deUint32 baseMipLevel,deUint32 baseArraySlice)3333 ImageFetchRenderInstance::ImageFetchRenderInstance (vkt::Context& context,
3334 bool isPrimaryCmdBuf,
3335 vk::VkDescriptorType descriptorType,
3336 vk::VkShaderStageFlags stageFlags,
3337 ShaderInputInterface shaderInterface,
3338 vk::VkImageViewType viewType,
3339 deUint32 baseMipLevel,
3340 deUint32 baseArraySlice)
3341 : SingleCmdRenderInstance (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
3342 , m_descriptorType (descriptorType)
3343 , m_stageFlags (stageFlags)
3344 , m_shaderInterface (shaderInterface)
3345 , m_viewType (viewType)
3346 , m_baseMipLevel (baseMipLevel)
3347 , m_baseArraySlice (baseArraySlice)
3348 , m_descriptorSetLayout (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
3349 , m_pipelineLayout (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
3350 , m_images (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice)
3351 , m_descriptorPool (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
3352 , m_descriptorSet (createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, m_images.getImageViewA(), m_images.getImageViewB()))
3353 {
3354 }
3355
createDescriptorSetLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags)3356 vk::Move<vk::VkDescriptorSetLayout> ImageFetchRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface& vki,
3357 vk::VkDevice device,
3358 vk::VkDescriptorType descriptorType,
3359 ShaderInputInterface shaderInterface,
3360 vk::VkShaderStageFlags stageFlags)
3361 {
3362 vk::DescriptorSetLayoutBuilder builder;
3363
3364 switch (shaderInterface)
3365 {
3366 case SHADER_INPUT_SINGLE_DESCRIPTOR:
3367 builder.addSingleBinding(descriptorType, stageFlags);
3368 break;
3369
3370 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3371 builder.addSingleBinding(descriptorType, stageFlags);
3372 builder.addSingleBinding(descriptorType, stageFlags);
3373 break;
3374
3375 case SHADER_INPUT_DESCRIPTOR_ARRAY:
3376 builder.addArrayBinding(descriptorType, 2u, stageFlags);
3377 break;
3378
3379 default:
3380 DE_FATAL("Impossible");
3381 }
3382
3383 return builder.build(vki, device);
3384 }
3385
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorSetLayout descriptorSetLayout)3386 vk::Move<vk::VkPipelineLayout> ImageFetchRenderInstance::createPipelineLayout (const vk::DeviceInterface& vki,
3387 vk::VkDevice device,
3388 vk::VkDescriptorSetLayout descriptorSetLayout)
3389 {
3390 const vk::VkPipelineLayoutCreateInfo createInfo =
3391 {
3392 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
3393 DE_NULL,
3394 (vk::VkPipelineLayoutCreateFlags)0,
3395 1, // descriptorSetCount
3396 &descriptorSetLayout, // pSetLayouts
3397 0u, // pushConstantRangeCount
3398 DE_NULL, // pPushConstantRanges
3399 };
3400 return vk::createPipelineLayout(vki, device, &createInfo);
3401 }
3402
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface)3403 vk::Move<vk::VkDescriptorPool> ImageFetchRenderInstance::createDescriptorPool (const vk::DeviceInterface& vki,
3404 vk::VkDevice device,
3405 vk::VkDescriptorType descriptorType,
3406 ShaderInputInterface shaderInterface)
3407 {
3408 return vk::DescriptorPoolBuilder()
3409 .addType(descriptorType, getInterfaceNumResources(shaderInterface))
3410 .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
3411 }
3412
createDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,vk::VkDescriptorPool pool,vk::VkImageView viewA,vk::VkImageView viewB)3413 vk::Move<vk::VkDescriptorSet> ImageFetchRenderInstance::createDescriptorSet (const vk::DeviceInterface& vki,
3414 vk::VkDevice device,
3415 vk::VkDescriptorType descriptorType,
3416 ShaderInputInterface shaderInterface,
3417 vk::VkDescriptorSetLayout layout,
3418 vk::VkDescriptorPool pool,
3419 vk::VkImageView viewA,
3420 vk::VkImageView viewB)
3421 {
3422 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(descriptorType);
3423 const vk::VkDescriptorImageInfo imageInfos[2] =
3424 {
3425 makeDescriptorImageInfo(viewA, imageLayout),
3426 makeDescriptorImageInfo(viewB, imageLayout),
3427 };
3428 const vk::VkDescriptorSetAllocateInfo allocInfo =
3429 {
3430 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
3431 DE_NULL,
3432 pool,
3433 1u,
3434 &layout
3435 };
3436
3437 vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
3438 vk::DescriptorSetUpdateBuilder builder;
3439
3440 switch (shaderInterface)
3441 {
3442 case SHADER_INPUT_SINGLE_DESCRIPTOR:
3443 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &imageInfos[0]);
3444 break;
3445
3446 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3447 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &imageInfos[0]);
3448 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &imageInfos[1]);
3449 break;
3450
3451 case SHADER_INPUT_DESCRIPTOR_ARRAY:
3452 builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, imageInfos);
3453 break;
3454
3455 default:
3456 DE_FATAL("Impossible");
3457 }
3458
3459 builder.update(vki, device);
3460 return descriptorSet;
3461 }
3462
logTestPlan(void) const3463 void ImageFetchRenderInstance::logTestPlan (void) const
3464 {
3465 std::ostringstream msg;
3466
3467 msg << "Rendering 2x2 grid.\n"
3468 << "Single descriptor set. Descriptor set contains "
3469 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
3470 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
3471 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
3472 (const char*)DE_NULL)
3473 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
3474 << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
3475
3476 if (m_baseMipLevel)
3477 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
3478 if (m_baseArraySlice)
3479 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
3480
3481 if (m_stageFlags == 0u)
3482 {
3483 msg << "Descriptors are not accessed in any shader stage.\n";
3484 }
3485 else
3486 {
3487 msg << "Color in each cell is fetched using the descriptor(s):\n";
3488
3489 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
3490 {
3491 msg << "Test sample " << resultNdx << ": fetching at position " << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
3492
3493 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
3494 {
3495 const int srcResourceNdx = (resultNdx % 2); // ABAB source
3496 msg << " from descriptor " << srcResourceNdx;
3497 }
3498
3499 msg << "\n";
3500 }
3501
3502 msg << "Descriptors are accessed in {"
3503 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
3504 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
3505 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
3506 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
3507 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : (""))
3508 << " } stages.";
3509 }
3510
3511 m_context.getTestContext().getLog()
3512 << tcu::TestLog::Message
3513 << msg.str()
3514 << tcu::TestLog::EndMessage;
3515 }
3516
getPipelineLayout(void) const3517 vk::VkPipelineLayout ImageFetchRenderInstance::getPipelineLayout (void) const
3518 {
3519 return *m_pipelineLayout;
3520 }
3521
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const3522 void ImageFetchRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
3523 {
3524 m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
3525 m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
3526 }
3527
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const3528 tcu::TestStatus ImageFetchRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
3529 {
3530 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
3531 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f);
3532 const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch
3533 const tcu::Vec4 sample0 = (!doFetch) ? (yellow) : (m_images.fetchImageValue(0));
3534 const tcu::Vec4 sample1 = (!doFetch) ? (green) : (m_images.fetchImageValue(1));
3535 const tcu::Vec4 sample2 = (!doFetch) ? (green) : (m_images.fetchImageValue(2));
3536 const tcu::Vec4 sample3 = (!doFetch) ? (yellow) : (m_images.fetchImageValue(3));
3537 tcu::Surface reference (m_targetSize.x(), m_targetSize.y());
3538
3539 drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
3540
3541 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
3542 return tcu::TestStatus::fail("Image verification failed");
3543 else
3544 return tcu::TestStatus::pass("Pass");
3545 }
3546
3547 class ImageFetchComputeInstance : public vkt::TestInstance
3548 {
3549 public:
3550 ImageFetchComputeInstance (vkt::Context& context,
3551 vk::VkDescriptorType descriptorType,
3552 ShaderInputInterface shaderInterface,
3553 vk::VkImageViewType viewType,
3554 deUint32 baseMipLevel,
3555 deUint32 baseArraySlice);
3556
3557 private:
3558 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (void) const;
3559 vk::Move<vk::VkDescriptorPool> createDescriptorPool (void) const;
3560 vk::Move<vk::VkDescriptorSet> createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
3561
3562 tcu::TestStatus iterate (void);
3563 void logTestPlan (void) const;
3564 tcu::TestStatus testResourceAccess (void);
3565
3566 const vk::VkDescriptorType m_descriptorType;
3567 const ShaderInputInterface m_shaderInterface;
3568 const vk::VkImageViewType m_viewType;
3569 const deUint32 m_baseMipLevel;
3570 const deUint32 m_baseArraySlice;
3571
3572 const vk::DeviceInterface& m_vki;
3573 const vk::VkDevice m_device;
3574 const vk::VkQueue m_queue;
3575 const deUint32 m_queueFamilyIndex;
3576 vk::Allocator& m_allocator;
3577
3578 const ComputeInstanceResultBuffer m_result;
3579 const ImageFetchInstanceImages m_images;
3580 };
3581
ImageFetchComputeInstance(Context & context,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,deUint32 baseMipLevel,deUint32 baseArraySlice)3582 ImageFetchComputeInstance::ImageFetchComputeInstance (Context& context,
3583 vk::VkDescriptorType descriptorType,
3584 ShaderInputInterface shaderInterface,
3585 vk::VkImageViewType viewType,
3586 deUint32 baseMipLevel,
3587 deUint32 baseArraySlice)
3588 : vkt::TestInstance (context)
3589 , m_descriptorType (descriptorType)
3590 , m_shaderInterface (shaderInterface)
3591 , m_viewType (viewType)
3592 , m_baseMipLevel (baseMipLevel)
3593 , m_baseArraySlice (baseArraySlice)
3594 , m_vki (context.getDeviceInterface())
3595 , m_device (context.getDevice())
3596 , m_queue (context.getUniversalQueue())
3597 , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
3598 , m_allocator (context.getDefaultAllocator())
3599 , m_result (m_vki, m_device, m_allocator)
3600 , m_images (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice)
3601 {
3602 }
3603
createDescriptorSetLayout(void) const3604 vk::Move<vk::VkDescriptorSetLayout> ImageFetchComputeInstance::createDescriptorSetLayout (void) const
3605 {
3606 vk::DescriptorSetLayoutBuilder builder;
3607
3608 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3609
3610 switch (m_shaderInterface)
3611 {
3612 case SHADER_INPUT_SINGLE_DESCRIPTOR:
3613 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3614 break;
3615
3616 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3617 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3618 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3619 break;
3620
3621 case SHADER_INPUT_DESCRIPTOR_ARRAY:
3622 builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3623 break;
3624
3625 default:
3626 DE_FATAL("Impossible");
3627 };
3628
3629 return builder.build(m_vki, m_device);
3630 }
3631
createDescriptorPool(void) const3632 vk::Move<vk::VkDescriptorPool> ImageFetchComputeInstance::createDescriptorPool (void) const
3633 {
3634 return vk::DescriptorPoolBuilder()
3635 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
3636 .addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
3637 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
3638 }
3639
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout) const3640 vk::Move<vk::VkDescriptorSet> ImageFetchComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
3641 {
3642 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
3643 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(m_descriptorType);
3644 const vk::VkDescriptorImageInfo imageInfos[2] =
3645 {
3646 makeDescriptorImageInfo(m_images.getImageViewA(), imageLayout),
3647 makeDescriptorImageInfo(m_images.getImageViewB(), imageLayout),
3648 };
3649 const vk::VkDescriptorSetAllocateInfo allocInfo =
3650 {
3651 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
3652 DE_NULL,
3653 pool,
3654 1u,
3655 &layout
3656 };
3657
3658 vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
3659 vk::DescriptorSetUpdateBuilder builder;
3660
3661 // result
3662 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
3663
3664 // images
3665 switch (m_shaderInterface)
3666 {
3667 case SHADER_INPUT_SINGLE_DESCRIPTOR:
3668 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &imageInfos[0]);
3669 break;
3670
3671 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3672 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &imageInfos[0]);
3673 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &imageInfos[1]);
3674 break;
3675
3676 case SHADER_INPUT_DESCRIPTOR_ARRAY:
3677 builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, imageInfos);
3678 break;
3679
3680 default:
3681 DE_FATAL("Impossible");
3682 }
3683
3684 builder.update(m_vki, m_device);
3685 return descriptorSet;
3686 }
3687
iterate(void)3688 tcu::TestStatus ImageFetchComputeInstance::iterate (void)
3689 {
3690 logTestPlan();
3691 return testResourceAccess();
3692 }
3693
logTestPlan(void) const3694 void ImageFetchComputeInstance::logTestPlan (void) const
3695 {
3696 std::ostringstream msg;
3697
3698 msg << "Fetching 4 values from image in compute shader.\n"
3699 << "Single descriptor set. Descriptor set contains "
3700 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
3701 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
3702 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
3703 (const char*)DE_NULL)
3704 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
3705 << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
3706
3707 if (m_baseMipLevel)
3708 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
3709 if (m_baseArraySlice)
3710 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
3711
3712 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
3713 {
3714 msg << "Test sample " << resultNdx << ": fetch at position " << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
3715
3716 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
3717 {
3718 const int srcResourceNdx = (resultNdx % 2); // ABAB source
3719 msg << " from descriptor " << srcResourceNdx;
3720 }
3721
3722 msg << "\n";
3723 }
3724
3725 m_context.getTestContext().getLog()
3726 << tcu::TestLog::Message
3727 << msg.str()
3728 << tcu::TestLog::EndMessage;
3729 }
3730
testResourceAccess(void)3731 tcu::TestStatus ImageFetchComputeInstance::testResourceAccess (void)
3732 {
3733 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout());
3734 const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool());
3735 const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout));
3736 const ComputePipeline pipeline (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
3737
3738 const vk::VkDescriptorSet descriptorSets[] = { *descriptorSet };
3739 const int numDescriptorSets = DE_LENGTH_OF_ARRAY(descriptorSets);
3740 const deUint32* const dynamicOffsets = DE_NULL;
3741 const int numDynamicOffsets = 0;
3742 const vk::VkBufferMemoryBarrier* const preBarriers = DE_NULL;
3743 const int numPreBarriers = 0;
3744 const vk::VkBufferMemoryBarrier* const postBarriers = m_result.getResultReadBarrier();
3745 const int numPostBarriers = 1;
3746
3747 const ComputeCommand compute (m_vki,
3748 m_device,
3749 pipeline.getPipeline(),
3750 pipeline.getPipelineLayout(),
3751 tcu::UVec3(4, 1, 1),
3752 numDescriptorSets, descriptorSets,
3753 numDynamicOffsets, dynamicOffsets,
3754 numPreBarriers, preBarriers,
3755 numPostBarriers, postBarriers);
3756
3757 tcu::Vec4 results[4];
3758 bool anyResultSet = false;
3759 bool allResultsOk = true;
3760
3761 compute.submitAndWait(m_queueFamilyIndex, m_queue);
3762 m_result.readResultContentsTo(&results);
3763
3764 // verify
3765 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
3766 {
3767 const tcu::Vec4 result = results[resultNdx];
3768 const tcu::Vec4 reference = m_images.fetchImageValue(resultNdx);
3769 const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f);
3770
3771 if (result != tcu::Vec4(-1.0f))
3772 anyResultSet = true;
3773
3774 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
3775 {
3776 allResultsOk = false;
3777
3778 m_context.getTestContext().getLog()
3779 << tcu::TestLog::Message
3780 << "Test sample " << resultNdx << ": Expected " << reference << ", got " << result
3781 << tcu::TestLog::EndMessage;
3782 }
3783 }
3784
3785 // read back and verify
3786 if (allResultsOk)
3787 return tcu::TestStatus::pass("Pass");
3788 else if (anyResultSet)
3789 return tcu::TestStatus::fail("Invalid result values");
3790 else
3791 {
3792 m_context.getTestContext().getLog()
3793 << tcu::TestLog::Message
3794 << "Result buffer was not written to."
3795 << tcu::TestLog::EndMessage;
3796 return tcu::TestStatus::fail("Result buffer was not written to");
3797 }
3798 }
3799
3800 class ImageSampleInstanceImages : private ImageInstanceImages
3801 {
3802 public:
3803 ImageSampleInstanceImages (const vk::DeviceInterface& vki,
3804 vk::VkDevice device,
3805 deUint32 queueFamilyIndex,
3806 vk::VkQueue queue,
3807 vk::Allocator& allocator,
3808 vk::VkDescriptorType descriptorType,
3809 ShaderInputInterface shaderInterface,
3810 vk::VkImageViewType viewType,
3811 deUint32 baseMipLevel,
3812 deUint32 baseArraySlice,
3813 bool immutable);
3814
3815 static tcu::Vec4 getSamplePos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int samplePosNdx);
3816 tcu::Vec4 fetchSampleValue (int samplePosNdx) const;
3817
getImageViewA(void) const3818 inline vk::VkImageView getImageViewA (void) const { return *m_imageViewA; }
getImageViewB(void) const3819 inline vk::VkImageView getImageViewB (void) const { return *m_imageViewB; }
getSamplerA(void) const3820 inline vk::VkSampler getSamplerA (void) const { return *m_samplerA; }
getSamplerB(void) const3821 inline vk::VkSampler getSamplerB (void) const { return *m_samplerB; }
isImmutable(void) const3822 inline bool isImmutable (void) const { return m_isImmutable; }
3823
3824 private:
3825 static int getNumImages (vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface);
3826 static tcu::Sampler createRefSampler (bool isFirst);
3827 static vk::Move<vk::VkSampler> createSampler (const vk::DeviceInterface& vki, vk::VkDevice device, const tcu::Sampler& sampler, const tcu::TextureFormat& format);
3828
3829 static tcu::Texture1DArrayView getRef1DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
3830 static tcu::Texture2DArrayView getRef2DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
3831 static tcu::Texture3DView getRef3DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
3832 static tcu::TextureCubeArrayView getRefCubeView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
3833
3834 const vk::VkDescriptorType m_descriptorType;
3835 const ShaderInputInterface m_shaderInterface;
3836 const bool m_isImmutable;
3837
3838 const tcu::Sampler m_refSamplerA;
3839 const tcu::Sampler m_refSamplerB;
3840 const vk::Unique<vk::VkSampler> m_samplerA;
3841 const vk::Unique<vk::VkSampler> m_samplerB;
3842 };
3843
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)3844 ImageSampleInstanceImages::ImageSampleInstanceImages (const vk::DeviceInterface& vki,
3845 vk::VkDevice device,
3846 deUint32 queueFamilyIndex,
3847 vk::VkQueue queue,
3848 vk::Allocator& allocator,
3849 vk::VkDescriptorType descriptorType,
3850 ShaderInputInterface shaderInterface,
3851 vk::VkImageViewType viewType,
3852 deUint32 baseMipLevel,
3853 deUint32 baseArraySlice,
3854 bool immutable)
3855 : ImageInstanceImages (vki,
3856 device,
3857 queueFamilyIndex,
3858 queue,
3859 allocator,
3860 descriptorType,
3861 viewType,
3862 getNumImages(descriptorType, shaderInterface),
3863 baseMipLevel,
3864 baseArraySlice)
3865 , m_descriptorType (descriptorType)
3866 , m_shaderInterface (shaderInterface)
3867 , m_isImmutable (immutable)
3868 , m_refSamplerA (createRefSampler(true))
3869 , m_refSamplerB (createRefSampler(false))
3870 , m_samplerA (createSampler(vki, device, m_refSamplerA, m_imageFormat))
3871 , m_samplerB ((getInterfaceNumResources(m_shaderInterface) == 1u)
3872 ? vk::Move<vk::VkSampler>()
3873 : createSampler(vki, device, m_refSamplerB, m_imageFormat))
3874 {
3875 }
3876
getSamplePos(vk::VkImageViewType viewType,deUint32 baseMipLevel,deUint32 baseArraySlice,int samplePosNdx)3877 tcu::Vec4 ImageSampleInstanceImages::getSamplePos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int samplePosNdx)
3878 {
3879 DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
3880
3881 const deUint32 imageSize = (deUint32)IMAGE_SIZE >> baseMipLevel;
3882 const deUint32 arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
3883
3884 // choose arbitrary values that are not ambiguous with NEAREST filtering
3885
3886 switch (viewType)
3887 {
3888 case vk::VK_IMAGE_VIEW_TYPE_1D:
3889 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
3890 case vk::VK_IMAGE_VIEW_TYPE_2D:
3891 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
3892 case vk::VK_IMAGE_VIEW_TYPE_3D:
3893 {
3894 const tcu::Vec3 coords[4] =
3895 {
3896 tcu::Vec3(0.75f,
3897 0.5f,
3898 (float)(12u % imageSize) + 0.25f),
3899
3900 tcu::Vec3((float)(23u % imageSize) + 0.25f,
3901 (float)(73u % imageSize) + 0.5f,
3902 (float)(16u % imageSize) + 0.5f + (float)imageSize),
3903
3904 tcu::Vec3(-(float)(43u % imageSize) + 0.25f,
3905 (float)(84u % imageSize) + 0.5f + (float)imageSize,
3906 (float)(117u % imageSize) + 0.75f),
3907
3908 tcu::Vec3((float)imageSize + 0.5f,
3909 (float)(75u % imageSize) + 0.25f,
3910 (float)(83u % imageSize) + 0.25f + (float)imageSize),
3911 };
3912 const deUint32 slices[4] =
3913 {
3914 0u % arraySize,
3915 4u % arraySize,
3916 9u % arraySize,
3917 2u % arraySize,
3918 };
3919
3920 if (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
3921 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
3922 (float)slices[samplePosNdx],
3923 0.0f,
3924 0.0f);
3925 else if (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)
3926 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
3927 coords[samplePosNdx].y() / (float)imageSize,
3928 (float)slices[samplePosNdx],
3929 0.0f);
3930 else if (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)
3931 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
3932 coords[samplePosNdx].y() / (float)imageSize,
3933 coords[samplePosNdx].z() / (float)imageSize,
3934 0.0f);
3935 else
3936 {
3937 DE_FATAL("Impossible");
3938 return tcu::Vec4();
3939 }
3940 }
3941
3942 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
3943 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
3944 {
3945 // \note these values are in [0, texSize]*3 space for convenience
3946 const tcu::Vec3 coords[4] =
3947 {
3948 tcu::Vec3(0.75f,
3949 0.5f,
3950 (float)imageSize),
3951
3952 tcu::Vec3((float)(13u % imageSize) + 0.25f,
3953 0.0f,
3954 (float)(16u % imageSize) + 0.5f),
3955
3956 tcu::Vec3(0.0f,
3957 (float)(84u % imageSize) + 0.5f,
3958 (float)(10u % imageSize) + 0.75f),
3959
3960 tcu::Vec3((float)imageSize,
3961 (float)(75u % imageSize) + 0.25f,
3962 (float)(83u % imageSize) + 0.75f),
3963 };
3964 const deUint32 slices[4] =
3965 {
3966 1u % arraySize,
3967 2u % arraySize,
3968 9u % arraySize,
3969 5u % arraySize,
3970 };
3971
3972 DE_ASSERT(de::inRange(coords[samplePosNdx].x(), 0.0f, (float)imageSize));
3973 DE_ASSERT(de::inRange(coords[samplePosNdx].y(), 0.0f, (float)imageSize));
3974 DE_ASSERT(de::inRange(coords[samplePosNdx].z(), 0.0f, (float)imageSize));
3975
3976 // map to [-1, 1]*3 space
3977 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize * 2.0f - 1.0f,
3978 coords[samplePosNdx].y() / (float)imageSize * 2.0f - 1.0f,
3979 coords[samplePosNdx].z() / (float)imageSize * 2.0f - 1.0f,
3980 (float)slices[samplePosNdx]);
3981 }
3982
3983 default:
3984 DE_FATAL("Impossible");
3985 return tcu::Vec4();
3986 }
3987 }
3988
fetchSampleValue(int samplePosNdx) const3989 tcu::Vec4 ImageSampleInstanceImages::fetchSampleValue (int samplePosNdx) const
3990 {
3991 DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
3992
3993 // texture order is ABAB
3994 const bool isSamplerCase = (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER);
3995 const tcu::TextureLevelPyramid& sampleSrcA = m_sourceImageA;
3996 const tcu::TextureLevelPyramid& sampleSrcB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_sourceImageA) : (m_sourceImageB);
3997 const tcu::TextureLevelPyramid& sampleSrc = (isSamplerCase) ? (sampleSrcA) : ((samplePosNdx % 2) == 0) ? (sampleSrcA) : (sampleSrcB);
3998
3999 // sampler order is ABAB
4000 const tcu::Sampler& samplerA = m_refSamplerA;
4001 const tcu::Sampler& samplerB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_refSamplerA) : (m_refSamplerB);
4002 const tcu::Sampler& sampler = ((samplePosNdx % 2) == 0) ? (samplerA) : (samplerB);
4003
4004 const tcu::Vec4 samplePos = getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
4005 const float lod = 0.0f;
4006 std::vector<tcu::ConstPixelBufferAccess> levelStorage;
4007
4008 switch (m_viewType)
4009 {
4010 case vk::VK_IMAGE_VIEW_TYPE_1D:
4011 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY: return getRef1DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), lod);
4012 case vk::VK_IMAGE_VIEW_TYPE_2D:
4013 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);
4014 case vk::VK_IMAGE_VIEW_TYPE_3D: return getRef3DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
4015 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
4016 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);
4017
4018 default:
4019 {
4020 DE_FATAL("Impossible");
4021 return tcu::Vec4();
4022 }
4023 }
4024 }
4025
getNumImages(vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface)4026 int ImageSampleInstanceImages::getNumImages (vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface)
4027 {
4028 // If we are testing separate samplers, just one image is enough
4029 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4030 return 1;
4031 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4032 {
4033 // combined: numImages == numSamplers
4034 return getInterfaceNumResources(shaderInterface);
4035 }
4036 else
4037 {
4038 DE_FATAL("Impossible");
4039 return 0;
4040 }
4041 }
4042
createRefSampler(bool isFirst)4043 tcu::Sampler ImageSampleInstanceImages::createRefSampler (bool isFirst)
4044 {
4045 if (isFirst)
4046 {
4047 // linear, wrapping
4048 return tcu::Sampler(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::LINEAR, tcu::Sampler::LINEAR);
4049 }
4050 else
4051 {
4052 // nearest, clamping
4053 return tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);
4054 }
4055 }
4056
createSampler(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::Sampler & sampler,const tcu::TextureFormat & format)4057 vk::Move<vk::VkSampler> ImageSampleInstanceImages::createSampler (const vk::DeviceInterface& vki, vk::VkDevice device, const tcu::Sampler& sampler, const tcu::TextureFormat& format)
4058 {
4059 const vk::VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, format);
4060
4061 return vk::createSampler(vki, device, &createInfo);
4062 }
4063
getRef1DView(const tcu::TextureLevelPyramid & source,deUint32 baseMipLevel,deUint32 baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)4064 tcu::Texture1DArrayView ImageSampleInstanceImages::getRef1DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
4065 {
4066 DE_ASSERT(levelStorage->empty());
4067
4068 const deUint32 numSlices = (deUint32)source.getLevel(0).getHeight();
4069 const deUint32 numLevels = (deUint32)source.getNumLevels();
4070
4071 // cut pyramid from baseMipLevel
4072 for (deUint32 level = baseMipLevel; level < numLevels; ++level)
4073 {
4074 // cut levels from baseArraySlice
4075 const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
4076 const tcu::ConstPixelBufferAccess cutLevel = tcu::getSubregion(wholeLevel, 0, baseArraySlice, wholeLevel.getWidth(), numSlices - baseArraySlice);
4077 levelStorage->push_back(cutLevel);
4078 }
4079
4080 return tcu::Texture1DArrayView((int)levelStorage->size(), &levelStorage->front());
4081 }
4082
getRef2DView(const tcu::TextureLevelPyramid & source,deUint32 baseMipLevel,deUint32 baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)4083 tcu::Texture2DArrayView ImageSampleInstanceImages::getRef2DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
4084 {
4085 DE_ASSERT(levelStorage->empty());
4086
4087 const deUint32 numSlices = (deUint32)source.getLevel(0).getDepth();
4088 const deUint32 numLevels = (deUint32)source.getNumLevels();
4089
4090 // cut pyramid from baseMipLevel
4091 for (deUint32 level = baseMipLevel; level < numLevels; ++level)
4092 {
4093 // cut levels from baseArraySlice
4094 const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
4095 const tcu::ConstPixelBufferAccess cutLevel = tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice, wholeLevel.getWidth(), wholeLevel.getHeight(), numSlices - baseArraySlice);
4096 levelStorage->push_back(cutLevel);
4097 }
4098
4099 return tcu::Texture2DArrayView((int)levelStorage->size(), &levelStorage->front());
4100 }
4101
getRef3DView(const tcu::TextureLevelPyramid & source,deUint32 baseMipLevel,deUint32 baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)4102 tcu::Texture3DView ImageSampleInstanceImages::getRef3DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
4103 {
4104 DE_ASSERT(levelStorage->empty());
4105 DE_ASSERT(baseArraySlice == 0);
4106 DE_UNREF(baseArraySlice);
4107
4108 const deUint32 numLevels = (deUint32)source.getNumLevels();
4109
4110 // cut pyramid from baseMipLevel
4111 for (deUint32 level = baseMipLevel; level < numLevels; ++level)
4112 levelStorage->push_back(source.getLevel(level));
4113
4114 return tcu::Texture3DView((int)levelStorage->size(), &levelStorage->front());
4115 }
4116
getRefCubeView(const tcu::TextureLevelPyramid & source,deUint32 baseMipLevel,deUint32 baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)4117 tcu::TextureCubeArrayView ImageSampleInstanceImages::getRefCubeView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
4118 {
4119 DE_ASSERT(levelStorage->empty());
4120
4121 const deUint32 numSlices = (deUint32)source.getLevel(0).getDepth() / 6;
4122 const deUint32 numLevels = (deUint32)source.getNumLevels();
4123
4124 // cut pyramid from baseMipLevel
4125 for (deUint32 level = baseMipLevel; level < numLevels; ++level)
4126 {
4127 // cut levels from baseArraySlice
4128 const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
4129 const tcu::ConstPixelBufferAccess cutLevel = tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice * 6, wholeLevel.getWidth(), wholeLevel.getHeight(), (numSlices - baseArraySlice) * 6);
4130 levelStorage->push_back(cutLevel);
4131 }
4132
4133 return tcu::TextureCubeArrayView((int)levelStorage->size(), &levelStorage->front());
4134 }
4135
4136 class ImageSampleRenderInstance : public SingleCmdRenderInstance
4137 {
4138 public:
4139 ImageSampleRenderInstance (vkt::Context& context,
4140 bool isPrimaryCmdBuf,
4141 vk::VkDescriptorType descriptorType,
4142 vk::VkShaderStageFlags stageFlags,
4143 ShaderInputInterface shaderInterface,
4144 vk::VkImageViewType viewType,
4145 deUint32 baseMipLevel,
4146 deUint32 baseArraySlice,
4147 bool isImmutable);
4148
4149 private:
4150 static vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vki,
4151 vk::VkDevice device,
4152 vk::VkDescriptorType descriptorType,
4153 ShaderInputInterface shaderInterface,
4154 vk::VkShaderStageFlags stageFlags,
4155 const ImageSampleInstanceImages& images);
4156
4157 static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki,
4158 vk::VkDevice device,
4159 vk::VkDescriptorSetLayout descriptorSetLayout);
4160
4161 static vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vki,
4162 vk::VkDevice device,
4163 vk::VkDescriptorType descriptorType,
4164 ShaderInputInterface shaderInterface);
4165
4166 static vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vki,
4167 vk::VkDevice device,
4168 vk::VkDescriptorType descriptorType,
4169 ShaderInputInterface shaderInterface,
4170 vk::VkDescriptorSetLayout layout,
4171 vk::VkDescriptorPool pool,
4172 bool isImmutable,
4173 const ImageSampleInstanceImages& images);
4174
4175 static void writeSamplerDescriptorSet (const vk::DeviceInterface& vki,
4176 vk::VkDevice device,
4177 ShaderInputInterface shaderInterface,
4178 bool isImmutable,
4179 const ImageSampleInstanceImages& images,
4180 vk::VkDescriptorSet descriptorSet);
4181
4182 static void writeImageSamplerDescriptorSet (const vk::DeviceInterface& vki,
4183 vk::VkDevice device,
4184 ShaderInputInterface shaderInterface,
4185 bool isImmutable,
4186 const ImageSampleInstanceImages& images,
4187 vk::VkDescriptorSet descriptorSet);
4188
4189 void logTestPlan (void) const;
4190 vk::VkPipelineLayout getPipelineLayout (void) const;
4191 void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const;
4192 tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const;
4193
4194 enum
4195 {
4196 RENDER_SIZE = 128,
4197 };
4198
4199 const vk::VkDescriptorType m_descriptorType;
4200 const vk::VkShaderStageFlags m_stageFlags;
4201 const ShaderInputInterface m_shaderInterface;
4202 const vk::VkImageViewType m_viewType;
4203 const deUint32 m_baseMipLevel;
4204 const deUint32 m_baseArraySlice;
4205
4206 const ImageSampleInstanceImages m_images;
4207 const vk::Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
4208 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
4209 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
4210 const vk::Unique<vk::VkDescriptorSet> m_descriptorSet;
4211 };
4212
ImageSampleRenderInstance(vkt::Context & context,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags stageFlags,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,deUint32 baseMipLevel,deUint32 baseArraySlice,bool isImmutable)4213 ImageSampleRenderInstance::ImageSampleRenderInstance (vkt::Context& context,
4214 bool isPrimaryCmdBuf,
4215 vk::VkDescriptorType descriptorType,
4216 vk::VkShaderStageFlags stageFlags,
4217 ShaderInputInterface shaderInterface,
4218 vk::VkImageViewType viewType,
4219 deUint32 baseMipLevel,
4220 deUint32 baseArraySlice,
4221 bool isImmutable)
4222 : SingleCmdRenderInstance (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
4223 , m_descriptorType (descriptorType)
4224 , m_stageFlags (stageFlags)
4225 , m_shaderInterface (shaderInterface)
4226 , m_viewType (viewType)
4227 , m_baseMipLevel (baseMipLevel)
4228 , m_baseArraySlice (baseArraySlice)
4229 , m_images (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, isImmutable)
4230 , m_descriptorSetLayout (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags, m_images))
4231 , m_pipelineLayout (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
4232 , m_descriptorPool (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
4233 , m_descriptorSet (createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, isImmutable, m_images))
4234 {
4235 }
4236
createDescriptorSetLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,const ImageSampleInstanceImages & images)4237 vk::Move<vk::VkDescriptorSetLayout> ImageSampleRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface& vki,
4238 vk::VkDevice device,
4239 vk::VkDescriptorType descriptorType,
4240 ShaderInputInterface shaderInterface,
4241 vk::VkShaderStageFlags stageFlags,
4242 const ImageSampleInstanceImages& images)
4243 {
4244 const vk::VkSampler samplers[2] =
4245 {
4246 images.getSamplerA(),
4247 images.getSamplerB(),
4248 };
4249
4250 vk::DescriptorSetLayoutBuilder builder;
4251 const bool addSeparateImage = descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER;
4252
4253 // (combined)samplers follow
4254 switch (shaderInterface)
4255 {
4256 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4257 if (addSeparateImage)
4258 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
4259 builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4260 break;
4261
4262 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4263 if (addSeparateImage)
4264 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
4265 builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4266 builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
4267 break;
4268
4269 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4270 builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4271 if (addSeparateImage)
4272 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
4273 builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
4274 break;
4275
4276 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4277 if (addSeparateImage)
4278 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
4279 builder.addArraySamplerBinding(descriptorType, 2u, stageFlags, (images.isImmutable()) ? (samplers) : (DE_NULL));
4280 break;
4281
4282 default:
4283 DE_FATAL("Impossible");
4284 }
4285
4286 return builder.build(vki, device);
4287 }
4288
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorSetLayout descriptorSetLayout)4289 vk::Move<vk::VkPipelineLayout> ImageSampleRenderInstance::createPipelineLayout (const vk::DeviceInterface& vki,
4290 vk::VkDevice device,
4291 vk::VkDescriptorSetLayout descriptorSetLayout)
4292 {
4293 const vk::VkPipelineLayoutCreateInfo createInfo =
4294 {
4295 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
4296 DE_NULL,
4297 (vk::VkPipelineLayoutCreateFlags)0,
4298 1, // descriptorSetCount
4299 &descriptorSetLayout, // pSetLayouts
4300 0u, // pushConstantRangeCount
4301 DE_NULL, // pPushConstantRanges
4302 };
4303 return vk::createPipelineLayout(vki, device, &createInfo);
4304 }
4305
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface)4306 vk::Move<vk::VkDescriptorPool> ImageSampleRenderInstance::createDescriptorPool (const vk::DeviceInterface& vki,
4307 vk::VkDevice device,
4308 vk::VkDescriptorType descriptorType,
4309 ShaderInputInterface shaderInterface)
4310 {
4311 vk::DescriptorPoolBuilder builder;
4312
4313 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4314 {
4315 // separate samplers need image to sample
4316 builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
4317
4318 // also need sample to use, indifferent of whether immutable or not
4319 builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLER, getInterfaceNumResources(shaderInterface));
4320 }
4321 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4322 {
4323 // combined image samplers
4324 builder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, getInterfaceNumResources(shaderInterface));
4325 }
4326 else
4327 DE_FATAL("Impossible");
4328
4329 return builder.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
4330 }
4331
createDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,vk::VkDescriptorPool pool,bool isImmutable,const ImageSampleInstanceImages & images)4332 vk::Move<vk::VkDescriptorSet> ImageSampleRenderInstance::createDescriptorSet (const vk::DeviceInterface& vki,
4333 vk::VkDevice device,
4334 vk::VkDescriptorType descriptorType,
4335 ShaderInputInterface shaderInterface,
4336 vk::VkDescriptorSetLayout layout,
4337 vk::VkDescriptorPool pool,
4338 bool isImmutable,
4339 const ImageSampleInstanceImages& images)
4340 {
4341 const vk::VkDescriptorSetAllocateInfo allocInfo =
4342 {
4343 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
4344 DE_NULL,
4345 pool,
4346 1u,
4347 &layout
4348 };
4349
4350 vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
4351
4352 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4353 writeSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet);
4354 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4355 writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet);
4356 else
4357 DE_FATAL("Impossible");
4358
4359 return descriptorSet;
4360 }
4361
writeSamplerDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,ShaderInputInterface shaderInterface,bool isImmutable,const ImageSampleInstanceImages & images,vk::VkDescriptorSet descriptorSet)4362 void ImageSampleRenderInstance::writeSamplerDescriptorSet (const vk::DeviceInterface& vki,
4363 vk::VkDevice device,
4364 ShaderInputInterface shaderInterface,
4365 bool isImmutable,
4366 const ImageSampleInstanceImages& images,
4367 vk::VkDescriptorSet descriptorSet)
4368 {
4369 const vk::VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
4370 const vk::VkDescriptorImageInfo samplersInfos[2] =
4371 {
4372 makeDescriptorImageInfo(images.getSamplerA()),
4373 makeDescriptorImageInfo(images.getSamplerB()),
4374 };
4375
4376 vk::DescriptorSetUpdateBuilder builder;
4377 const deUint32 samplerLocation = shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS ? 1u : 0u;
4378
4379 // stand alone texture
4380 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(samplerLocation), vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
4381
4382 // samplers
4383 if (!isImmutable)
4384 {
4385 switch (shaderInterface)
4386 {
4387 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4388 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4389 break;
4390
4391 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4392 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4393 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
4394 break;
4395
4396 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4397 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4398 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
4399 break;
4400
4401 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4402 builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
4403 break;
4404
4405 default:
4406 DE_FATAL("Impossible");
4407 }
4408 }
4409
4410 builder.update(vki, device);
4411 }
4412
writeImageSamplerDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,ShaderInputInterface shaderInterface,bool isImmutable,const ImageSampleInstanceImages & images,vk::VkDescriptorSet descriptorSet)4413 void ImageSampleRenderInstance::writeImageSamplerDescriptorSet (const vk::DeviceInterface& vki,
4414 vk::VkDevice device,
4415 ShaderInputInterface shaderInterface,
4416 bool isImmutable,
4417 const ImageSampleInstanceImages& images,
4418 vk::VkDescriptorSet descriptorSet)
4419 {
4420 const vk::VkSampler samplers[2] =
4421 {
4422 (isImmutable) ? (0) : (images.getSamplerA()),
4423 (isImmutable) ? (0) : (images.getSamplerB()),
4424 };
4425 const vk::VkDescriptorImageInfo imageSamplers[2] =
4426 {
4427 vk::makeDescriptorImageInfo(samplers[0], images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
4428 vk::makeDescriptorImageInfo(samplers[1], images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
4429 };
4430
4431 vk::DescriptorSetUpdateBuilder builder;
4432
4433 // combined image samplers
4434 switch (shaderInterface)
4435 {
4436 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4437 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
4438 break;
4439
4440 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4441 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
4442 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
4443 break;
4444
4445 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4446 builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
4447 break;
4448
4449 default:
4450 DE_FATAL("Impossible");
4451 }
4452
4453 builder.update(vki, device);
4454 }
4455
logTestPlan(void) const4456 void ImageSampleRenderInstance::logTestPlan (void) const
4457 {
4458 std::ostringstream msg;
4459
4460 msg << "Rendering 2x2 grid.\n";
4461
4462 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4463 {
4464 msg << "Single descriptor set. Descriptor set contains "
4465 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4466 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
4467 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
4468 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4469 (const char*)DE_NULL)
4470 << " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
4471 }
4472 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4473 {
4474 msg << "Single descriptor set. Descriptor set contains "
4475 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4476 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
4477 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
4478 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4479 (const char*)DE_NULL)
4480 << " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
4481 }
4482 else
4483 DE_FATAL("Impossible");
4484
4485 msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
4486
4487 if (m_baseMipLevel)
4488 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
4489 if (m_baseArraySlice)
4490 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
4491
4492 if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
4493 msg << "Sampler mode is LINEAR, with WRAP\n";
4494 else
4495 msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
4496
4497 if (m_stageFlags == 0u)
4498 {
4499 msg << "Descriptors are not accessed in any shader stage.\n";
4500 }
4501 else
4502 {
4503 msg << "Color in each cell is fetched using the descriptor(s):\n";
4504
4505 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
4506 {
4507 msg << "Test sample " << resultNdx << ": sample at position " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
4508
4509 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
4510 {
4511 const int srcResourceNdx = (resultNdx % 2); // ABAB source
4512
4513 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4514 msg << " using sampler " << srcResourceNdx;
4515 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4516 msg << " from combined image sampler " << srcResourceNdx;
4517 else
4518 DE_FATAL("Impossible");
4519 }
4520 msg << "\n";
4521 }
4522
4523 msg << "Descriptors are accessed in {"
4524 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
4525 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
4526 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
4527 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
4528 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : (""))
4529 << " } stages.";
4530 }
4531
4532 m_context.getTestContext().getLog()
4533 << tcu::TestLog::Message
4534 << msg.str()
4535 << tcu::TestLog::EndMessage;
4536 }
4537
getPipelineLayout(void) const4538 vk::VkPipelineLayout ImageSampleRenderInstance::getPipelineLayout (void) const
4539 {
4540 return *m_pipelineLayout;
4541 }
4542
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const4543 void ImageSampleRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
4544 {
4545 m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
4546 m_vki.cmdDraw(cmd, 6u * 4u, 1u, 0u, 0u); // render four quads (two separate triangles)
4547 }
4548
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const4549 tcu::TestStatus ImageSampleRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
4550 {
4551 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
4552 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f);
4553 const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch
4554 const tcu::Vec4 sample0 = (!doFetch) ? (yellow) : (m_images.fetchSampleValue(0));
4555 const tcu::Vec4 sample1 = (!doFetch) ? (green) : (m_images.fetchSampleValue(1));
4556 const tcu::Vec4 sample2 = (!doFetch) ? (green) : (m_images.fetchSampleValue(2));
4557 const tcu::Vec4 sample3 = (!doFetch) ? (yellow) : (m_images.fetchSampleValue(3));
4558 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
4559 tcu::Surface reference (m_targetSize.x(), m_targetSize.y());
4560
4561 drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
4562
4563 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, threshold, tcu::COMPARE_LOG_RESULT))
4564 return tcu::TestStatus::fail("Image verification failed");
4565 else
4566 return tcu::TestStatus::pass("Pass");
4567 }
4568
4569 class ImageSampleComputeInstance : public vkt::TestInstance
4570 {
4571 public:
4572 ImageSampleComputeInstance (vkt::Context& context,
4573 vk::VkDescriptorType descriptorType,
4574 ShaderInputInterface shaderInterface,
4575 vk::VkImageViewType viewType,
4576 deUint32 baseMipLevel,
4577 deUint32 baseArraySlice,
4578 bool isImmutableSampler);
4579
4580 private:
4581 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (void) const;
4582 vk::Move<vk::VkDescriptorPool> createDescriptorPool (void) const;
4583 vk::Move<vk::VkDescriptorSet> createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
4584 void writeImageSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const;
4585 void writeSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const;
4586
4587 tcu::TestStatus iterate (void);
4588 void logTestPlan (void) const;
4589 tcu::TestStatus testResourceAccess (void);
4590
4591 const vk::VkDescriptorType m_descriptorType;
4592 const ShaderInputInterface m_shaderInterface;
4593 const vk::VkImageViewType m_viewType;
4594 const deUint32 m_baseMipLevel;
4595 const deUint32 m_baseArraySlice;
4596 const bool m_isImmutableSampler;
4597
4598 const vk::DeviceInterface& m_vki;
4599 const vk::VkDevice m_device;
4600 const vk::VkQueue m_queue;
4601 const deUint32 m_queueFamilyIndex;
4602 vk::Allocator& m_allocator;
4603
4604 const ComputeInstanceResultBuffer m_result;
4605 const ImageSampleInstanceImages m_images;
4606 };
4607
ImageSampleComputeInstance(Context & context,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,deUint32 baseMipLevel,deUint32 baseArraySlice,bool isImmutableSampler)4608 ImageSampleComputeInstance::ImageSampleComputeInstance (Context& context,
4609 vk::VkDescriptorType descriptorType,
4610 ShaderInputInterface shaderInterface,
4611 vk::VkImageViewType viewType,
4612 deUint32 baseMipLevel,
4613 deUint32 baseArraySlice,
4614 bool isImmutableSampler)
4615 : vkt::TestInstance (context)
4616 , m_descriptorType (descriptorType)
4617 , m_shaderInterface (shaderInterface)
4618 , m_viewType (viewType)
4619 , m_baseMipLevel (baseMipLevel)
4620 , m_baseArraySlice (baseArraySlice)
4621 , m_isImmutableSampler (isImmutableSampler)
4622 , m_vki (context.getDeviceInterface())
4623 , m_device (context.getDevice())
4624 , m_queue (context.getUniversalQueue())
4625 , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
4626 , m_allocator (context.getDefaultAllocator())
4627 , m_result (m_vki, m_device, m_allocator)
4628 , m_images (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, isImmutableSampler)
4629 {
4630 }
4631
createDescriptorSetLayout(void) const4632 vk::Move<vk::VkDescriptorSetLayout> ImageSampleComputeInstance::createDescriptorSetLayout (void) const
4633 {
4634 const vk::VkSampler samplers[2] =
4635 {
4636 m_images.getSamplerA(),
4637 m_images.getSamplerB(),
4638 };
4639
4640 vk::DescriptorSetLayoutBuilder builder;
4641
4642 // result buffer
4643 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4644
4645 // with samplers, separate texture at binding 0
4646 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4647 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4648
4649 // (combined)samplers follow
4650 switch (m_shaderInterface)
4651 {
4652 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4653 builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4654 break;
4655
4656 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4657 builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4658 builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
4659 break;
4660
4661 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4662 builder.addArraySamplerBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (samplers) : (DE_NULL));
4663 break;
4664
4665 default:
4666 DE_FATAL("Impossible");
4667 };
4668
4669 return builder.build(m_vki, m_device);
4670 }
4671
createDescriptorPool(void) const4672 vk::Move<vk::VkDescriptorPool> ImageSampleComputeInstance::createDescriptorPool (void) const
4673 {
4674 vk::DescriptorPoolBuilder builder;
4675
4676 builder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
4677 builder.addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface));
4678
4679 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4680 builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
4681
4682 return builder.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
4683 }
4684
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout) const4685 vk::Move<vk::VkDescriptorSet> ImageSampleComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
4686 {
4687 const vk::VkDescriptorSetAllocateInfo allocInfo =
4688 {
4689 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
4690 DE_NULL,
4691 pool,
4692 1u,
4693 &layout
4694 };
4695
4696 vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
4697
4698 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4699 writeSamplerDescriptorSet(*descriptorSet);
4700 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4701 writeImageSamplerDescriptorSet(*descriptorSet);
4702 else
4703 DE_FATAL("Impossible");
4704
4705 return descriptorSet;
4706 }
4707
writeSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet) const4708 void ImageSampleComputeInstance::writeSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const
4709 {
4710 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4711 const vk::VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
4712 const vk::VkDescriptorImageInfo samplersInfos[2] =
4713 {
4714 makeDescriptorImageInfo(m_images.getSamplerA()),
4715 makeDescriptorImageInfo(m_images.getSamplerB()),
4716 };
4717
4718 vk::DescriptorSetUpdateBuilder builder;
4719
4720 // result
4721 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
4722
4723 // stand alone texture
4724 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
4725
4726 // samplers
4727 if (!m_isImmutableSampler)
4728 {
4729 switch (m_shaderInterface)
4730 {
4731 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4732 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4733 break;
4734
4735 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4736 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4737 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(3u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
4738 break;
4739
4740 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4741 builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
4742 break;
4743
4744 default:
4745 DE_FATAL("Impossible");
4746 }
4747 }
4748
4749 builder.update(m_vki, m_device);
4750 }
4751
writeImageSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet) const4752 void ImageSampleComputeInstance::writeImageSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const
4753 {
4754 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4755 const vk::VkSampler samplers[2] =
4756 {
4757 (m_isImmutableSampler) ? (0) : (m_images.getSamplerA()),
4758 (m_isImmutableSampler) ? (0) : (m_images.getSamplerB()),
4759 };
4760 const vk::VkDescriptorImageInfo imageSamplers[2] =
4761 {
4762 makeDescriptorImageInfo(samplers[0], m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
4763 makeDescriptorImageInfo(samplers[1], m_images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
4764 };
4765
4766 vk::DescriptorSetUpdateBuilder builder;
4767
4768 // result
4769 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
4770
4771 // combined image samplers
4772 switch (m_shaderInterface)
4773 {
4774 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4775 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
4776 break;
4777
4778 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4779 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
4780 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
4781 break;
4782
4783 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4784 builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
4785 break;
4786
4787 default:
4788 DE_FATAL("Impossible");
4789 }
4790
4791 builder.update(m_vki, m_device);
4792 }
4793
iterate(void)4794 tcu::TestStatus ImageSampleComputeInstance::iterate (void)
4795 {
4796 logTestPlan();
4797 return testResourceAccess();
4798 }
4799
logTestPlan(void) const4800 void ImageSampleComputeInstance::logTestPlan (void) const
4801 {
4802 std::ostringstream msg;
4803
4804 msg << "Accessing resource in a compute program.\n";
4805
4806 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4807 {
4808 msg << "Single descriptor set. Descriptor set contains "
4809 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4810 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
4811 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4812 (const char*)DE_NULL)
4813 << " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
4814 }
4815 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4816 {
4817 msg << "Single descriptor set. Descriptor set contains "
4818 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4819 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
4820 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4821 (const char*)DE_NULL)
4822 << " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
4823 }
4824 else
4825 DE_FATAL("Impossible");
4826
4827 msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
4828
4829 if (m_baseMipLevel)
4830 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
4831 if (m_baseArraySlice)
4832 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
4833
4834 if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
4835 msg << "Sampler mode is LINEAR, with WRAP\n";
4836 else
4837 msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
4838
4839 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
4840 {
4841 msg << "Test sample " << resultNdx << ": sample at position " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
4842
4843 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
4844 {
4845 const int srcResourceNdx = (resultNdx % 2); // ABAB source
4846
4847 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4848 msg << " using sampler " << srcResourceNdx;
4849 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4850 msg << " from combined image sampler " << srcResourceNdx;
4851 else
4852 DE_FATAL("Impossible");
4853 }
4854 msg << "\n";
4855 }
4856
4857 m_context.getTestContext().getLog()
4858 << tcu::TestLog::Message
4859 << msg.str()
4860 << tcu::TestLog::EndMessage;
4861 }
4862
testResourceAccess(void)4863 tcu::TestStatus ImageSampleComputeInstance::testResourceAccess (void)
4864 {
4865 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout());
4866 const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool());
4867 const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout));
4868 const ComputePipeline pipeline (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
4869
4870 const vk::VkDescriptorSet descriptorSets[] = { *descriptorSet };
4871 const int numDescriptorSets = DE_LENGTH_OF_ARRAY(descriptorSets);
4872 const deUint32* const dynamicOffsets = DE_NULL;
4873 const int numDynamicOffsets = 0;
4874 const vk::VkBufferMemoryBarrier* const preBarriers = DE_NULL;
4875 const int numPreBarriers = 0;
4876 const vk::VkBufferMemoryBarrier* const postBarriers = m_result.getResultReadBarrier();
4877 const int numPostBarriers = 1;
4878
4879 const ComputeCommand compute (m_vki,
4880 m_device,
4881 pipeline.getPipeline(),
4882 pipeline.getPipelineLayout(),
4883 tcu::UVec3(4, 1, 1),
4884 numDescriptorSets, descriptorSets,
4885 numDynamicOffsets, dynamicOffsets,
4886 numPreBarriers, preBarriers,
4887 numPostBarriers, postBarriers);
4888
4889 tcu::Vec4 results[4];
4890 bool anyResultSet = false;
4891 bool allResultsOk = true;
4892
4893 compute.submitAndWait(m_queueFamilyIndex, m_queue);
4894 m_result.readResultContentsTo(&results);
4895
4896 // verify
4897 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
4898 {
4899 const tcu::Vec4 result = results[resultNdx];
4900 const tcu::Vec4 reference = m_images.fetchSampleValue(resultNdx);
4901
4902 // source image is high-frequency so the threshold is quite large to tolerate sampling errors
4903 const tcu::Vec4 samplingThreshold = tcu::Vec4(8.0f / 255.0f);
4904
4905 if (result != tcu::Vec4(-1.0f))
4906 anyResultSet = true;
4907
4908 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), samplingThreshold)))
4909 {
4910 allResultsOk = false;
4911
4912 m_context.getTestContext().getLog()
4913 << tcu::TestLog::Message
4914 << "Test sample " << resultNdx << ":\n"
4915 << "\tSampling at " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx) << "\n"
4916 << "\tError expected " << reference << ", got " << result
4917 << tcu::TestLog::EndMessage;
4918 }
4919 }
4920
4921 // read back and verify
4922 if (allResultsOk)
4923 return tcu::TestStatus::pass("Pass");
4924 else if (anyResultSet)
4925 return tcu::TestStatus::fail("Invalid result values");
4926 else
4927 {
4928 m_context.getTestContext().getLog()
4929 << tcu::TestLog::Message
4930 << "Result buffer was not written to."
4931 << tcu::TestLog::EndMessage;
4932 return tcu::TestStatus::fail("Result buffer was not written to");
4933 }
4934 }
4935
4936 class ImageDescriptorCase : public QuadrantRendederCase
4937 {
4938 public:
4939 enum
4940 {
4941 FLAG_BASE_MIP = (1u << 1u),
4942 FLAG_BASE_SLICE = (1u << 2u),
4943 };
4944 // enum continues where resource flags ends
4945 DE_STATIC_ASSERT((deUint32)FLAG_BASE_MIP == (deUint32)RESOURCE_FLAG_LAST);
4946
4947 ImageDescriptorCase (tcu::TestContext& testCtx,
4948 const char* name,
4949 const char* description,
4950 bool isPrimaryCmdBuf,
4951 vk::VkDescriptorType descriptorType,
4952 vk::VkShaderStageFlags exitingStages,
4953 vk::VkShaderStageFlags activeStages,
4954 ShaderInputInterface shaderInterface,
4955 vk::VkImageViewType viewType,
4956 deUint32 flags);
4957
4958 private:
4959 std::string genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const;
4960 std::string genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
4961 std::string genFetchCoordStr (int fetchPosNdx) const;
4962 std::string genSampleCoordStr (int samplePosNdx) const;
4963 std::string genResourceAccessSource (vk::VkShaderStageFlagBits stage) const;
4964 std::string genNoAccessSource (void) const;
4965
4966 vkt::TestInstance* createInstance (vkt::Context& context) const;
4967
4968 private:
4969 const bool m_isPrimaryCmdBuf;
4970 const vk::VkDescriptorType m_descriptorType;
4971 const ShaderInputInterface m_shaderInterface;
4972 const vk::VkImageViewType m_viewType;
4973 const deUint32 m_baseMipLevel;
4974 const deUint32 m_baseArraySlice;
4975 const bool m_isImmutableSampler;
4976 };
4977
ImageDescriptorCase(tcu::TestContext & testCtx,const char * name,const char * description,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,deUint32 flags)4978 ImageDescriptorCase::ImageDescriptorCase (tcu::TestContext& testCtx,
4979 const char* name,
4980 const char* description,
4981 bool isPrimaryCmdBuf,
4982 vk::VkDescriptorType descriptorType,
4983 vk::VkShaderStageFlags exitingStages,
4984 vk::VkShaderStageFlags activeStages,
4985 ShaderInputInterface shaderInterface,
4986 vk::VkImageViewType viewType,
4987 deUint32 flags)
4988 : QuadrantRendederCase (testCtx, name, description,
4989 // \note 1D textures are not supported in ES
4990 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? glu::GLSL_VERSION_440 : glu::GLSL_VERSION_310_ES,
4991 exitingStages, activeStages)
4992 , m_isPrimaryCmdBuf (isPrimaryCmdBuf)
4993 , m_descriptorType (descriptorType)
4994 , m_shaderInterface (shaderInterface)
4995 , m_viewType (viewType)
4996 , m_baseMipLevel (((flags & FLAG_BASE_MIP) != 0) ? (1u) : (0u))
4997 , m_baseArraySlice (((flags & FLAG_BASE_SLICE) != 0) ? (1u) : (0u))
4998 , m_isImmutableSampler ((flags & RESOURCE_FLAG_IMMUTABLE_SAMPLER) != 0)
4999 {
5000 }
5001
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const5002 std::string ImageDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const
5003 {
5004 DE_UNREF(stage);
5005
5006 if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
5007 return "#extension GL_OES_texture_cube_map_array : require\n";
5008 else
5009 return "";
5010 }
5011
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const5012 std::string ImageDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const
5013 {
5014 DE_UNREF(stage);
5015
5016 // Vulkan-style resources are arrays implicitly, OpenGL-style are not
5017 const std::string dimensionBase = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? ("1D")
5018 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? ("2D")
5019 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ("3D")
5020 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("Cube")
5021 : (DE_NULL);
5022 const std::string dimensionArray = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? ("1DArray")
5023 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? ("2DArray")
5024 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ("3D")
5025 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("CubeArray")
5026 : (DE_NULL);
5027 const std::string dimension = isImageViewTypeArray(m_viewType) ? dimensionArray : dimensionBase;
5028
5029 if (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS)
5030 DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER);
5031
5032 switch (m_shaderInterface)
5033 {
5034 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5035 {
5036 switch (m_descriptorType)
5037 {
5038 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5039 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
5040 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSampler;\n";
5041 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5042 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSampler;\n";
5043 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
5044 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture;\n";
5045 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5046 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_image;\n";
5047 default:
5048 DE_FATAL("invalid descriptor");
5049 return "";
5050 }
5051 }
5052
5053 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5054 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
5055 switch (m_descriptorType)
5056 {
5057 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5058 if (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)
5059 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
5060 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSamplerA;\n"
5061 "layout(set = 0, binding = " + de::toString(numUsedBindings+2) + ") uniform highp sampler u_separateSamplerB;\n";
5062 else
5063 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler u_separateSamplerA;\n"
5064 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
5065 "layout(set = 0, binding = " + de::toString(numUsedBindings+2) + ") uniform highp sampler u_separateSamplerB;\n";
5066 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5067 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSamplerA;\n"
5068 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler" + dimension + " u_combinedTextureSamplerB;\n";
5069 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
5070 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTextureA;\n"
5071 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp texture" + dimensionBase + " u_separateTextureB;\n";
5072 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5073 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_imageA;\n"
5074 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ", rgba8) readonly uniform highp image" + dimension + " u_imageB;\n";
5075 default:
5076 DE_FATAL("invalid descriptor");
5077 return "";
5078 }
5079
5080 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5081 switch (m_descriptorType)
5082 {
5083 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5084 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
5085 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSampler[2];\n";
5086 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5087 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSampler[2];\n";
5088 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
5089 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture[2];\n";
5090 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5091 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_image[2];\n";
5092 default:
5093 DE_FATAL("invalid descriptor");
5094 return "";
5095 }
5096
5097 default:
5098 DE_FATAL("Impossible");
5099 return "";
5100 }
5101 }
5102
genFetchCoordStr(int fetchPosNdx) const5103 std::string ImageDescriptorCase::genFetchCoordStr (int fetchPosNdx) const
5104 {
5105 DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || m_descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
5106 const tcu::IVec3 fetchPos = ImageFetchInstanceImages::getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
5107
5108 if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
5109 {
5110 return de::toString(fetchPos.x());
5111 }
5112 else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
5113 {
5114 std::ostringstream buf;
5115 buf << "ivec2(" << fetchPos.x() << ", " << fetchPos.y() << ")";
5116 return buf.str();
5117 }
5118 else
5119 {
5120 std::ostringstream buf;
5121 buf << "ivec3(" << fetchPos.x() << ", " << fetchPos.y() << ", " << fetchPos.z() << ")";
5122 return buf.str();
5123 }
5124 }
5125
genSampleCoordStr(int samplePosNdx) const5126 std::string ImageDescriptorCase::genSampleCoordStr (int samplePosNdx) const
5127 {
5128 DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER || m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
5129 const tcu::Vec4 fetchPos = ImageSampleInstanceImages::getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
5130
5131 if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
5132 {
5133 std::ostringstream buf;
5134 buf << "float(" << fetchPos.x() << ")";
5135 return buf.str();
5136 }
5137 else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
5138 {
5139 std::ostringstream buf;
5140 buf << "vec2(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "))";
5141 return buf.str();
5142 }
5143 else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
5144 {
5145 std::ostringstream buf;
5146 buf << "vec4(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "), float(" << fetchPos.w() << "))";
5147 return buf.str();
5148 }
5149 else
5150 {
5151 std::ostringstream buf;
5152 buf << "vec3(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "))";
5153 return buf.str();
5154 }
5155 }
5156
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const5157 std::string ImageDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const
5158 {
5159 DE_UNREF(stage);
5160
5161 const char* const dimension = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D) ? ("1D")
5162 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? ("1DArray")
5163 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D) ? ("2D")
5164 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? ("2DArray")
5165 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ("3D")
5166 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE) ? ("Cube")
5167 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("CubeArray")
5168 : (DE_NULL);
5169 const char* const accessPostfixA = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("")
5170 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("A")
5171 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("A")
5172 : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[0]")
5173 : (DE_NULL);
5174 const char* const accessPostfixB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("")
5175 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("B")
5176 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("B")
5177 : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[1]")
5178 : (DE_NULL);
5179
5180 switch (m_descriptorType)
5181 {
5182 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5183 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5184 {
5185 const std::string coodStr[4] =
5186 {
5187 genSampleCoordStr(0),
5188 genSampleCoordStr(1),
5189 genSampleCoordStr(2),
5190 genSampleCoordStr(3),
5191 };
5192 std::ostringstream buf;
5193
5194 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5195 {
5196 buf << " if (quadrant_id == 0)\n"
5197 << " result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixA << "), " << coodStr[0] << ", 0.0);\n"
5198 << " else if (quadrant_id == 1)\n"
5199 << " result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixB << "), " << coodStr[1] << ", 0.0);\n"
5200 << " else if (quadrant_id == 2)\n"
5201 << " result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixA << "), " << coodStr[2] << ", 0.0);\n"
5202 << " else\n"
5203 << " result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixB << "), " << coodStr[3] << ", 0.0);\n";
5204 }
5205 else
5206 {
5207 buf << " if (quadrant_id == 0)\n"
5208 << " result_color = textureLod(u_combinedTextureSampler" << accessPostfixA << ", " << coodStr[0] << ", 0.0);\n"
5209 << " else if (quadrant_id == 1)\n"
5210 << " result_color = textureLod(u_combinedTextureSampler" << accessPostfixB << ", " << coodStr[1] << ", 0.0);\n"
5211 << " else if (quadrant_id == 2)\n"
5212 << " result_color = textureLod(u_combinedTextureSampler" << accessPostfixA << ", " << coodStr[2] << ", 0.0);\n"
5213 << " else\n"
5214 << " result_color = textureLod(u_combinedTextureSampler" << accessPostfixB << ", " << coodStr[3] << ", 0.0);\n";
5215 }
5216
5217 return buf.str();
5218 }
5219
5220 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5221 {
5222 const std::string coodStr[4] =
5223 {
5224 genFetchCoordStr(0),
5225 genFetchCoordStr(1),
5226 genFetchCoordStr(2),
5227 genFetchCoordStr(3),
5228 };
5229 std::ostringstream buf;
5230
5231 buf << " if (quadrant_id == 0)\n"
5232 << " result_color = imageLoad(u_image" << accessPostfixA << ", " << coodStr[0] << ");\n"
5233 << " else if (quadrant_id == 1)\n"
5234 << " result_color = imageLoad(u_image" << accessPostfixB << ", " << coodStr[1] << ");\n"
5235 << " else if (quadrant_id == 2)\n"
5236 << " result_color = imageLoad(u_image" << accessPostfixA << ", " << coodStr[2] << ");\n"
5237 << " else\n"
5238 << " result_color = imageLoad(u_image" << accessPostfixB << ", " << coodStr[3] << ");\n";
5239
5240 return buf.str();
5241 }
5242
5243 default:
5244 DE_FATAL("invalid descriptor");
5245 return "";
5246 }
5247 }
5248
genNoAccessSource(void) const5249 std::string ImageDescriptorCase::genNoAccessSource (void) const
5250 {
5251 return " if (quadrant_id == 1 || quadrant_id == 2)\n"
5252 " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
5253 " else\n"
5254 " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
5255 }
5256
createInstance(vkt::Context & context) const5257 vkt::TestInstance* ImageDescriptorCase::createInstance (vkt::Context& context) const
5258 {
5259 verifyDriverSupport(context.getDeviceFeatures(), m_descriptorType, m_activeStages);
5260
5261 switch (m_descriptorType)
5262 {
5263 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5264 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5265 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
5266 {
5267 DE_ASSERT(m_isPrimaryCmdBuf);
5268 return new ImageSampleComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_isImmutableSampler);
5269 }
5270 else
5271 return new ImageSampleRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_isImmutableSampler);
5272
5273 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
5274 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5275 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
5276 {
5277 DE_ASSERT(m_isPrimaryCmdBuf);
5278 return new ImageFetchComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice);
5279 }
5280 else
5281 return new ImageFetchRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice);
5282
5283 default:
5284 DE_FATAL("Impossible");
5285 return DE_NULL;
5286 }
5287 }
5288
5289 class TexelBufferInstanceBuffers
5290 {
5291 public:
5292 TexelBufferInstanceBuffers (const vk::DeviceInterface& vki,
5293 vk::VkDevice device,
5294 vk::Allocator& allocator,
5295 vk::VkDescriptorType descriptorType,
5296 int numTexelBuffers,
5297 bool hasViewOffset);
5298
5299 private:
5300 static vk::Move<vk::VkBuffer> createBuffer (const vk::DeviceInterface& vki,
5301 vk::VkDevice device,
5302 vk::Allocator& allocator,
5303 vk::VkDescriptorType descriptorType,
5304 de::MovePtr<vk::Allocation> *outAllocation);
5305
5306 static vk::Move<vk::VkBufferView> createBufferView (const vk::DeviceInterface& vki,
5307 vk::VkDevice device,
5308 const tcu::TextureFormat& textureFormat,
5309 deUint32 offset,
5310 vk::VkBuffer buffer);
5311
5312 static vk::VkBufferMemoryBarrier createBarrier (vk::VkDescriptorType descriptorType, vk::VkBuffer buffer);
5313
5314 void populateSourceBuffer (const tcu::PixelBufferAccess& access);
5315 void uploadData (const vk::DeviceInterface& vki, vk::VkDevice device, const vk::Allocation& memory, const de::ArrayBuffer<deUint8>& data);
5316
5317 public:
5318 static int getFetchPos (int fetchPosNdx);
5319 tcu::Vec4 fetchTexelValue (int fetchPosNdx) const;
5320
getNumTexelBuffers(void) const5321 inline int getNumTexelBuffers (void) const { return m_numTexelBuffers; }
getTextureFormat(void) const5322 const tcu::TextureFormat& getTextureFormat (void) const { return m_imageFormat; }
getBufferViewA(void) const5323 inline vk::VkBufferView getBufferViewA (void) const { return *m_bufferViewA; }
getBufferViewB(void) const5324 inline vk::VkBufferView getBufferViewB (void) const { return *m_bufferViewB; }
getBufferInitBarriers(void) const5325 inline const vk::VkBufferMemoryBarrier* getBufferInitBarriers (void) const { return m_bufferBarriers; }
5326
5327 private:
5328 enum
5329 {
5330 BUFFER_SIZE = 512,
5331 VIEW_OFFSET_VALUE = 256,
5332 VIEW_DATA_SIZE = 256, //!< size in bytes
5333 VIEW_WIDTH = 64, //!< size in pixels
5334 };
5335 enum
5336 {
5337 // some arbitrary points
5338 SAMPLE_POINT_0 = 6,
5339 SAMPLE_POINT_1 = 51,
5340 SAMPLE_POINT_2 = 42,
5341 SAMPLE_POINT_3 = 25,
5342 };
5343
5344 const deUint32 m_numTexelBuffers;
5345 const tcu::TextureFormat m_imageFormat;
5346 const deUint32 m_viewOffset;
5347
5348 de::ArrayBuffer<deUint8> m_sourceBufferA;
5349 de::ArrayBuffer<deUint8> m_sourceBufferB;
5350 const tcu::ConstPixelBufferAccess m_sourceViewA;
5351 const tcu::ConstPixelBufferAccess m_sourceViewB;
5352
5353 de::MovePtr<vk::Allocation> m_bufferMemoryA;
5354 de::MovePtr<vk::Allocation> m_bufferMemoryB;
5355 const vk::Unique<vk::VkBuffer> m_bufferA;
5356 const vk::Unique<vk::VkBuffer> m_bufferB;
5357 const vk::Unique<vk::VkBufferView> m_bufferViewA;
5358 const vk::Unique<vk::VkBufferView> m_bufferViewB;
5359 vk::VkBufferMemoryBarrier m_bufferBarriers[2];
5360 };
5361
TexelBufferInstanceBuffers(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,int numTexelBuffers,bool hasViewOffset)5362 TexelBufferInstanceBuffers::TexelBufferInstanceBuffers (const vk::DeviceInterface& vki,
5363 vk::VkDevice device,
5364 vk::Allocator& allocator,
5365 vk::VkDescriptorType descriptorType,
5366 int numTexelBuffers,
5367 bool hasViewOffset)
5368 : m_numTexelBuffers (numTexelBuffers)
5369 , m_imageFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
5370 , m_viewOffset ((hasViewOffset) ? ((deUint32)VIEW_OFFSET_VALUE) : (0u))
5371 , m_sourceBufferA (BUFFER_SIZE)
5372 , m_sourceBufferB ((numTexelBuffers == 1)
5373 ? (0u)
5374 : ((size_t)BUFFER_SIZE))
5375 , m_sourceViewA (m_imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1), m_sourceBufferA.getElementPtr(m_viewOffset))
5376 , m_sourceViewB (m_imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1), m_sourceBufferB.getElementPtr(m_viewOffset))
5377 , m_bufferMemoryA (DE_NULL)
5378 , m_bufferMemoryB (DE_NULL)
5379 , m_bufferA (createBuffer(vki, device, allocator, descriptorType, &m_bufferMemoryA))
5380 , m_bufferB ((numTexelBuffers == 1)
5381 ? vk::Move<vk::VkBuffer>()
5382 : createBuffer(vki, device, allocator, descriptorType, &m_bufferMemoryB))
5383 , m_bufferViewA (createBufferView(vki, device, m_imageFormat, m_viewOffset, *m_bufferA))
5384 , m_bufferViewB ((numTexelBuffers == 1)
5385 ? vk::Move<vk::VkBufferView>()
5386 : createBufferView(vki, device, m_imageFormat, m_viewOffset, *m_bufferB))
5387 {
5388 DE_ASSERT(numTexelBuffers == 1 || numTexelBuffers == 2);
5389 DE_ASSERT(VIEW_WIDTH * m_imageFormat.getPixelSize() == VIEW_DATA_SIZE);
5390 DE_ASSERT(BUFFER_SIZE % m_imageFormat.getPixelSize() == 0);
5391
5392 // specify and upload
5393
5394 populateSourceBuffer(tcu::PixelBufferAccess(m_imageFormat, tcu::IVec3(BUFFER_SIZE / m_imageFormat.getPixelSize(), 1, 1), m_sourceBufferA.getPtr()));
5395 uploadData(vki, device, *m_bufferMemoryA, m_sourceBufferA);
5396
5397 if (numTexelBuffers == 2)
5398 {
5399 populateSourceBuffer(tcu::PixelBufferAccess(m_imageFormat, tcu::IVec3(BUFFER_SIZE / m_imageFormat.getPixelSize(), 1, 1), m_sourceBufferB.getPtr()));
5400 uploadData(vki, device, *m_bufferMemoryB, m_sourceBufferB);
5401 }
5402
5403 m_bufferBarriers[0] = createBarrier(descriptorType, *m_bufferA);
5404 m_bufferBarriers[1] = createBarrier(descriptorType, *m_bufferB);
5405 }
5406
createBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,de::MovePtr<vk::Allocation> * outAllocation)5407 vk::Move<vk::VkBuffer> TexelBufferInstanceBuffers::createBuffer (const vk::DeviceInterface& vki,
5408 vk::VkDevice device,
5409 vk::Allocator& allocator,
5410 vk::VkDescriptorType descriptorType,
5411 de::MovePtr<vk::Allocation> *outAllocation)
5412 {
5413 const vk::VkBufferUsageFlags usage = (isUniformDescriptorType(descriptorType)) ? (vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
5414 const vk::VkBufferCreateInfo createInfo =
5415 {
5416 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
5417 DE_NULL,
5418 0u, // flags
5419 (vk::VkDeviceSize)BUFFER_SIZE, // size
5420 usage, // usage
5421 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
5422 0u, // queueFamilyCount
5423 DE_NULL, // pQueueFamilyIndices
5424 };
5425 vk::Move<vk::VkBuffer> buffer (vk::createBuffer(vki, device, &createInfo));
5426 de::MovePtr<vk::Allocation> allocation (allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
5427
5428 *outAllocation = allocation;
5429 return buffer;
5430 }
5431
createBufferView(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::TextureFormat & textureFormat,deUint32 offset,vk::VkBuffer buffer)5432 vk::Move<vk::VkBufferView> TexelBufferInstanceBuffers::createBufferView (const vk::DeviceInterface& vki,
5433 vk::VkDevice device,
5434 const tcu::TextureFormat& textureFormat,
5435 deUint32 offset,
5436 vk::VkBuffer buffer)
5437 {
5438 const vk::VkBufferViewCreateInfo createInfo =
5439 {
5440 vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
5441 DE_NULL,
5442 (vk::VkBufferViewCreateFlags)0,
5443 buffer, // buffer
5444 vk::mapTextureFormat(textureFormat), // format
5445 (vk::VkDeviceSize)offset, // offset
5446 (vk::VkDeviceSize)VIEW_DATA_SIZE // range
5447 };
5448 return vk::createBufferView(vki, device, &createInfo);
5449 }
5450
createBarrier(vk::VkDescriptorType descriptorType,vk::VkBuffer buffer)5451 vk::VkBufferMemoryBarrier TexelBufferInstanceBuffers::createBarrier (vk::VkDescriptorType descriptorType, vk::VkBuffer buffer)
5452 {
5453 const vk::VkAccessFlags inputBit = (isUniformDescriptorType(descriptorType)) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
5454 const vk::VkBufferMemoryBarrier barrier =
5455 {
5456 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
5457 DE_NULL,
5458 vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask
5459 inputBit, // inputMask
5460 vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
5461 vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
5462 buffer , // buffer
5463 0u, // offset
5464 (vk::VkDeviceSize)BUFFER_SIZE // size
5465 };
5466 return barrier;
5467 }
5468
populateSourceBuffer(const tcu::PixelBufferAccess & access)5469 void TexelBufferInstanceBuffers::populateSourceBuffer (const tcu::PixelBufferAccess& access)
5470 {
5471 DE_ASSERT(access.getHeight() == 1);
5472 DE_ASSERT(access.getDepth() == 1);
5473
5474 const deInt32 width = access.getWidth();
5475
5476 for (int x = 0; x < width; ++x)
5477 {
5478 const int red = 255 * x / width; //!< gradient from 0 -> max (detects large offset errors)
5479 const int green = ((x % 2 == 0) ? (127) : (0)) + ((x % 4 < 3) ? (128) : (0)); //!< 3-level M pattern (detects small offset errors)
5480 const int blue = 16 * (x % 16); //!< 16-long triangle wave
5481
5482 DE_ASSERT(de::inRange(red, 0, 255));
5483 DE_ASSERT(de::inRange(green, 0, 255));
5484 DE_ASSERT(de::inRange(blue, 0, 255));
5485
5486 access.setPixel(tcu::IVec4(red, green, blue, 255), x, 0, 0);
5487 }
5488 }
5489
uploadData(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::Allocation & memory,const de::ArrayBuffer<deUint8> & data)5490 void TexelBufferInstanceBuffers::uploadData (const vk::DeviceInterface& vki, vk::VkDevice device, const vk::Allocation& memory, const de::ArrayBuffer<deUint8>& data)
5491 {
5492 deMemcpy(memory.getHostPtr(), data.getPtr(), data.size());
5493 flushMappedMemoryRange(vki, device, memory.getMemory(), memory.getOffset(), data.size());
5494 }
5495
getFetchPos(int fetchPosNdx)5496 int TexelBufferInstanceBuffers::getFetchPos (int fetchPosNdx)
5497 {
5498 static const int fetchPositions[4] =
5499 {
5500 SAMPLE_POINT_0,
5501 SAMPLE_POINT_1,
5502 SAMPLE_POINT_2,
5503 SAMPLE_POINT_3,
5504 };
5505 return de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
5506 }
5507
fetchTexelValue(int fetchPosNdx) const5508 tcu::Vec4 TexelBufferInstanceBuffers::fetchTexelValue (int fetchPosNdx) const
5509 {
5510 // source order is ABAB
5511 const tcu::ConstPixelBufferAccess& texelSrcA = m_sourceViewA;
5512 const tcu::ConstPixelBufferAccess& texelSrcB = (m_numTexelBuffers == 1) ? (m_sourceViewA) : (m_sourceViewB);
5513 const tcu::ConstPixelBufferAccess& texelSrc = ((fetchPosNdx % 2) == 0) ? (texelSrcA) : (texelSrcB);
5514
5515 return texelSrc.getPixel(getFetchPos(fetchPosNdx), 0, 0);
5516 }
5517
5518 class TexelBufferRenderInstance : public SingleCmdRenderInstance
5519 {
5520 public:
5521 TexelBufferRenderInstance (vkt::Context& context,
5522 bool isPrimaryCmdBuf,
5523 vk::VkDescriptorType descriptorType,
5524 vk::VkShaderStageFlags stageFlags,
5525 ShaderInputInterface shaderInterface,
5526 bool nonzeroViewOffset);
5527
5528 private:
5529 static vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vki,
5530 vk::VkDevice device,
5531 vk::VkDescriptorType descriptorType,
5532 ShaderInputInterface shaderInterface,
5533 vk::VkShaderStageFlags stageFlags);
5534
5535 static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki,
5536 vk::VkDevice device,
5537 vk::VkDescriptorSetLayout descriptorSetLayout);
5538
5539 static vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vki,
5540 vk::VkDevice device,
5541 vk::VkDescriptorType descriptorType,
5542 ShaderInputInterface shaderInterface);
5543
5544 static vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vki,
5545 vk::VkDevice device,
5546 vk::VkDescriptorType descriptorType,
5547 ShaderInputInterface shaderInterface,
5548 vk::VkDescriptorSetLayout layout,
5549 vk::VkDescriptorPool pool,
5550 vk::VkBufferView viewA,
5551 vk::VkBufferView viewB);
5552
5553 void logTestPlan (void) const;
5554 vk::VkPipelineLayout getPipelineLayout (void) const;
5555 void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const;
5556 tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const;
5557
5558 enum
5559 {
5560 RENDER_SIZE = 128,
5561 };
5562
5563 const vk::VkDescriptorType m_descriptorType;
5564 const vk::VkShaderStageFlags m_stageFlags;
5565 const ShaderInputInterface m_shaderInterface;
5566 const bool m_nonzeroViewOffset;
5567
5568 const vk::Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
5569 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
5570 const TexelBufferInstanceBuffers m_texelBuffers;
5571 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
5572 const vk::Unique<vk::VkDescriptorSet> m_descriptorSet;
5573 };
5574
TexelBufferRenderInstance(vkt::Context & context,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags stageFlags,ShaderInputInterface shaderInterface,bool nonzeroViewOffset)5575 TexelBufferRenderInstance::TexelBufferRenderInstance (vkt::Context& context,
5576 bool isPrimaryCmdBuf,
5577 vk::VkDescriptorType descriptorType,
5578 vk::VkShaderStageFlags stageFlags,
5579 ShaderInputInterface shaderInterface,
5580 bool nonzeroViewOffset)
5581 : SingleCmdRenderInstance (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
5582 , m_descriptorType (descriptorType)
5583 , m_stageFlags (stageFlags)
5584 , m_shaderInterface (shaderInterface)
5585 , m_nonzeroViewOffset (nonzeroViewOffset)
5586 , m_descriptorSetLayout (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
5587 , m_pipelineLayout (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
5588 , m_texelBuffers (m_vki, m_device, m_allocator, m_descriptorType, getInterfaceNumResources(m_shaderInterface), m_nonzeroViewOffset)
5589 , m_descriptorPool (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
5590 , m_descriptorSet (createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, m_texelBuffers.getBufferViewA(), m_texelBuffers.getBufferViewB()))
5591 {
5592 }
5593
createDescriptorSetLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags)5594 vk::Move<vk::VkDescriptorSetLayout> TexelBufferRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface& vki,
5595 vk::VkDevice device,
5596 vk::VkDescriptorType descriptorType,
5597 ShaderInputInterface shaderInterface,
5598 vk::VkShaderStageFlags stageFlags)
5599 {
5600 vk::DescriptorSetLayoutBuilder builder;
5601
5602 switch (shaderInterface)
5603 {
5604 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5605 builder.addSingleBinding(descriptorType, stageFlags);
5606 break;
5607
5608 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5609 builder.addSingleBinding(descriptorType, stageFlags);
5610 builder.addSingleBinding(descriptorType, stageFlags);
5611 break;
5612
5613 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5614 builder.addArrayBinding(descriptorType, 2u, stageFlags);
5615 break;
5616
5617 default:
5618 DE_FATAL("Impossible");
5619 }
5620
5621 return builder.build(vki, device);
5622 }
5623
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorSetLayout descriptorSetLayout)5624 vk::Move<vk::VkPipelineLayout> TexelBufferRenderInstance::createPipelineLayout (const vk::DeviceInterface& vki,
5625 vk::VkDevice device,
5626 vk::VkDescriptorSetLayout descriptorSetLayout)
5627 {
5628 const vk::VkPipelineLayoutCreateInfo createInfo =
5629 {
5630 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
5631 DE_NULL,
5632 (vk::VkPipelineLayoutCreateFlags)0,
5633 1, // descriptorSetCount
5634 &descriptorSetLayout, // pSetLayouts
5635 0u, // pushConstantRangeCount
5636 DE_NULL, // pPushConstantRanges
5637 };
5638 return vk::createPipelineLayout(vki, device, &createInfo);
5639 }
5640
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface)5641 vk::Move<vk::VkDescriptorPool> TexelBufferRenderInstance::createDescriptorPool (const vk::DeviceInterface& vki,
5642 vk::VkDevice device,
5643 vk::VkDescriptorType descriptorType,
5644 ShaderInputInterface shaderInterface)
5645 {
5646 return vk::DescriptorPoolBuilder()
5647 .addType(descriptorType, getInterfaceNumResources(shaderInterface))
5648 .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
5649 }
5650
createDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,vk::VkDescriptorPool pool,vk::VkBufferView viewA,vk::VkBufferView viewB)5651 vk::Move<vk::VkDescriptorSet> TexelBufferRenderInstance::createDescriptorSet (const vk::DeviceInterface& vki,
5652 vk::VkDevice device,
5653 vk::VkDescriptorType descriptorType,
5654 ShaderInputInterface shaderInterface,
5655 vk::VkDescriptorSetLayout layout,
5656 vk::VkDescriptorPool pool,
5657 vk::VkBufferView viewA,
5658 vk::VkBufferView viewB)
5659 {
5660 const vk::VkBufferView texelBufferInfos[2] =
5661 {
5662 viewA,
5663 viewB,
5664 };
5665 const vk::VkDescriptorSetAllocateInfo allocInfo =
5666 {
5667 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
5668 DE_NULL,
5669 pool,
5670 1u,
5671 &layout
5672 };
5673
5674 vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
5675 vk::DescriptorSetUpdateBuilder builder;
5676
5677 switch (shaderInterface)
5678 {
5679 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5680 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &texelBufferInfos[0]);
5681 break;
5682
5683 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5684 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &texelBufferInfos[0]);
5685 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &texelBufferInfos[1]);
5686 break;
5687
5688 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5689 builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, texelBufferInfos);
5690 break;
5691
5692 default:
5693 DE_FATAL("Impossible");
5694 }
5695
5696 builder.update(vki, device);
5697 return descriptorSet;
5698 }
5699
logTestPlan(void) const5700 void TexelBufferRenderInstance::logTestPlan (void) const
5701 {
5702 std::ostringstream msg;
5703
5704 msg << "Rendering 2x2 grid.\n"
5705 << "Single descriptor set. Descriptor set contains "
5706 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
5707 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
5708 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
5709 (const char*)DE_NULL)
5710 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
5711 << "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
5712 << "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
5713
5714 if (m_stageFlags == 0u)
5715 {
5716 msg << "Descriptors are not accessed in any shader stage.\n";
5717 }
5718 else
5719 {
5720 msg << "Color in each cell is fetched using the descriptor(s):\n";
5721
5722 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5723 {
5724 msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
5725
5726 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
5727 {
5728 const int srcResourceNdx = (resultNdx % 2); // ABAB source
5729 msg << " from texelBuffer " << srcResourceNdx;
5730 }
5731
5732 msg << "\n";
5733 }
5734
5735 msg << "Descriptors are accessed in {"
5736 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
5737 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
5738 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
5739 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
5740 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : (""))
5741 << " } stages.";
5742 }
5743
5744 m_context.getTestContext().getLog()
5745 << tcu::TestLog::Message
5746 << msg.str()
5747 << tcu::TestLog::EndMessage;
5748 }
5749
getPipelineLayout(void) const5750 vk::VkPipelineLayout TexelBufferRenderInstance::getPipelineLayout (void) const
5751 {
5752 return *m_pipelineLayout;
5753 }
5754
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const5755 void TexelBufferRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
5756 {
5757 m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
5758 m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
5759 }
5760
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const5761 tcu::TestStatus TexelBufferRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
5762 {
5763 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
5764 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f);
5765 const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch
5766 const tcu::Vec4 sample0 = (!doFetch) ? (yellow) : (m_texelBuffers.fetchTexelValue(0));
5767 const tcu::Vec4 sample1 = (!doFetch) ? (green) : (m_texelBuffers.fetchTexelValue(1));
5768 const tcu::Vec4 sample2 = (!doFetch) ? (green) : (m_texelBuffers.fetchTexelValue(2));
5769 const tcu::Vec4 sample3 = (!doFetch) ? (yellow) : (m_texelBuffers.fetchTexelValue(3));
5770 tcu::Surface reference (m_targetSize.x(), m_targetSize.y());
5771
5772 drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
5773
5774 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
5775 return tcu::TestStatus::fail("Image verification failed");
5776 else
5777 return tcu::TestStatus::pass("Pass");
5778 }
5779
5780 class TexelBufferComputeInstance : public vkt::TestInstance
5781 {
5782 public:
5783 TexelBufferComputeInstance (vkt::Context& context,
5784 vk::VkDescriptorType descriptorType,
5785 ShaderInputInterface shaderInterface,
5786 bool nonzeroViewOffset);
5787
5788 private:
5789 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (void) const;
5790 vk::Move<vk::VkDescriptorPool> createDescriptorPool (void) const;
5791 vk::Move<vk::VkDescriptorSet> createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
5792
5793 tcu::TestStatus iterate (void);
5794 void logTestPlan (void) const;
5795 tcu::TestStatus testResourceAccess (void);
5796
5797 const vk::VkDescriptorType m_descriptorType;
5798 const ShaderInputInterface m_shaderInterface;
5799 const bool m_nonzeroViewOffset;
5800
5801 const vk::DeviceInterface& m_vki;
5802 const vk::VkDevice m_device;
5803 const vk::VkQueue m_queue;
5804 const deUint32 m_queueFamilyIndex;
5805 vk::Allocator& m_allocator;
5806
5807 const ComputeInstanceResultBuffer m_result;
5808 const TexelBufferInstanceBuffers m_texelBuffers;
5809 };
5810
TexelBufferComputeInstance(Context & context,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,bool nonzeroViewOffset)5811 TexelBufferComputeInstance::TexelBufferComputeInstance (Context& context,
5812 vk::VkDescriptorType descriptorType,
5813 ShaderInputInterface shaderInterface,
5814 bool nonzeroViewOffset)
5815 : vkt::TestInstance (context)
5816 , m_descriptorType (descriptorType)
5817 , m_shaderInterface (shaderInterface)
5818 , m_nonzeroViewOffset (nonzeroViewOffset)
5819 , m_vki (context.getDeviceInterface())
5820 , m_device (context.getDevice())
5821 , m_queue (context.getUniversalQueue())
5822 , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
5823 , m_allocator (context.getDefaultAllocator())
5824 , m_result (m_vki, m_device, m_allocator)
5825 , m_texelBuffers (m_vki, m_device, m_allocator, m_descriptorType, getInterfaceNumResources(m_shaderInterface), m_nonzeroViewOffset)
5826 {
5827 }
5828
createDescriptorSetLayout(void) const5829 vk::Move<vk::VkDescriptorSetLayout> TexelBufferComputeInstance::createDescriptorSetLayout (void) const
5830 {
5831 vk::DescriptorSetLayoutBuilder builder;
5832
5833 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5834
5835 switch (m_shaderInterface)
5836 {
5837 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5838 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5839 break;
5840
5841 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5842 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5843 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5844 break;
5845
5846 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5847 builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5848 break;
5849
5850 default:
5851 DE_FATAL("Impossible");
5852 };
5853
5854 return builder.build(m_vki, m_device);
5855 }
5856
createDescriptorPool(void) const5857 vk::Move<vk::VkDescriptorPool> TexelBufferComputeInstance::createDescriptorPool (void) const
5858 {
5859 return vk::DescriptorPoolBuilder()
5860 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
5861 .addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
5862 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
5863 }
5864
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout) const5865 vk::Move<vk::VkDescriptorSet> TexelBufferComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
5866 {
5867 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
5868 const vk::VkBufferView texelBufferInfos[2] =
5869 {
5870 m_texelBuffers.getBufferViewA(),
5871 m_texelBuffers.getBufferViewB(),
5872 };
5873 const vk::VkDescriptorSetAllocateInfo allocInfo =
5874 {
5875 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
5876 DE_NULL,
5877 pool,
5878 1u,
5879 &layout
5880 };
5881
5882 vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
5883 vk::DescriptorSetUpdateBuilder builder;
5884
5885 // result
5886 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
5887
5888 // texel buffers
5889 switch (m_shaderInterface)
5890 {
5891 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5892 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &texelBufferInfos[0]);
5893 break;
5894
5895 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5896 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &texelBufferInfos[0]);
5897 builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &texelBufferInfos[1]);
5898 break;
5899
5900 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5901 builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, texelBufferInfos);
5902 break;
5903
5904 default:
5905 DE_FATAL("Impossible");
5906 }
5907
5908 builder.update(m_vki, m_device);
5909 return descriptorSet;
5910 }
5911
iterate(void)5912 tcu::TestStatus TexelBufferComputeInstance::iterate (void)
5913 {
5914 logTestPlan();
5915 return testResourceAccess();
5916 }
5917
logTestPlan(void) const5918 void TexelBufferComputeInstance::logTestPlan (void) const
5919 {
5920 std::ostringstream msg;
5921
5922 msg << "Fetching 4 values from image in compute shader.\n"
5923 << "Single descriptor set. Descriptor set contains "
5924 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
5925 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
5926 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
5927 (const char*)DE_NULL)
5928 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
5929 << "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
5930 << "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
5931
5932 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5933 {
5934 msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
5935
5936 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
5937 {
5938 const int srcResourceNdx = (resultNdx % 2); // ABAB source
5939 msg << " from texelBuffer " << srcResourceNdx;
5940 }
5941
5942 msg << "\n";
5943 }
5944
5945 m_context.getTestContext().getLog()
5946 << tcu::TestLog::Message
5947 << msg.str()
5948 << tcu::TestLog::EndMessage;
5949 }
5950
testResourceAccess(void)5951 tcu::TestStatus TexelBufferComputeInstance::testResourceAccess (void)
5952 {
5953 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout());
5954 const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool());
5955 const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout));
5956 const ComputePipeline pipeline (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
5957
5958 const vk::VkDescriptorSet descriptorSets[] = { *descriptorSet };
5959 const int numDescriptorSets = DE_LENGTH_OF_ARRAY(descriptorSets);
5960 const deUint32* const dynamicOffsets = DE_NULL;
5961 const int numDynamicOffsets = 0;
5962 const vk::VkBufferMemoryBarrier* const preBarriers = m_texelBuffers.getBufferInitBarriers();
5963 const int numPreBarriers = m_texelBuffers.getNumTexelBuffers();
5964 const vk::VkBufferMemoryBarrier* const postBarriers = m_result.getResultReadBarrier();
5965 const int numPostBarriers = 1;
5966
5967 const ComputeCommand compute (m_vki,
5968 m_device,
5969 pipeline.getPipeline(),
5970 pipeline.getPipelineLayout(),
5971 tcu::UVec3(4, 1, 1),
5972 numDescriptorSets, descriptorSets,
5973 numDynamicOffsets, dynamicOffsets,
5974 numPreBarriers, preBarriers,
5975 numPostBarriers, postBarriers);
5976
5977 tcu::Vec4 results[4];
5978 bool anyResultSet = false;
5979 bool allResultsOk = true;
5980
5981 compute.submitAndWait(m_queueFamilyIndex, m_queue);
5982 m_result.readResultContentsTo(&results);
5983
5984 // verify
5985 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5986 {
5987 const tcu::Vec4 result = results[resultNdx];
5988 const tcu::Vec4 reference = m_texelBuffers.fetchTexelValue(resultNdx);
5989 const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f);
5990
5991 if (result != tcu::Vec4(-1.0f))
5992 anyResultSet = true;
5993
5994 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
5995 {
5996 allResultsOk = false;
5997
5998 m_context.getTestContext().getLog()
5999 << tcu::TestLog::Message
6000 << "Test sample " << resultNdx << ": Expected " << reference << ", got " << result
6001 << tcu::TestLog::EndMessage;
6002 }
6003 }
6004
6005 // read back and verify
6006 if (allResultsOk)
6007 return tcu::TestStatus::pass("Pass");
6008 else if (anyResultSet)
6009 return tcu::TestStatus::fail("Invalid result values");
6010 else
6011 {
6012 m_context.getTestContext().getLog()
6013 << tcu::TestLog::Message
6014 << "Result buffer was not written to."
6015 << tcu::TestLog::EndMessage;
6016 return tcu::TestStatus::fail("Result buffer was not written to");
6017 }
6018 }
6019
6020 class TexelBufferDescriptorCase : public QuadrantRendederCase
6021 {
6022 public:
6023 enum
6024 {
6025 FLAG_VIEW_OFFSET = (1u << 1u),
6026 };
6027 // enum continues where resource flags ends
6028 DE_STATIC_ASSERT((deUint32)FLAG_VIEW_OFFSET == (deUint32)RESOURCE_FLAG_LAST);
6029
6030 TexelBufferDescriptorCase (tcu::TestContext& testCtx,
6031 const char* name,
6032 const char* description,
6033 bool isPrimaryCmdBuf,
6034 vk::VkDescriptorType descriptorType,
6035 vk::VkShaderStageFlags exitingStages,
6036 vk::VkShaderStageFlags activeStages,
6037 ShaderInputInterface shaderInterface,
6038 deUint32 flags);
6039
6040 private:
6041 std::string genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const;
6042 std::string genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
6043 std::string genResourceAccessSource (vk::VkShaderStageFlagBits stage) const;
6044 std::string genNoAccessSource (void) const;
6045
6046 vkt::TestInstance* createInstance (vkt::Context& context) const;
6047
6048 const bool m_isPrimaryCmdBuf;
6049 const vk::VkDescriptorType m_descriptorType;
6050 const ShaderInputInterface m_shaderInterface;
6051 const bool m_nonzeroViewOffset;
6052 };
6053
TexelBufferDescriptorCase(tcu::TestContext & testCtx,const char * name,const char * description,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,ShaderInputInterface shaderInterface,deUint32 flags)6054 TexelBufferDescriptorCase::TexelBufferDescriptorCase (tcu::TestContext& testCtx,
6055 const char* name,
6056 const char* description,
6057 bool isPrimaryCmdBuf,
6058 vk::VkDescriptorType descriptorType,
6059 vk::VkShaderStageFlags exitingStages,
6060 vk::VkShaderStageFlags activeStages,
6061 ShaderInputInterface shaderInterface,
6062 deUint32 flags)
6063 : QuadrantRendederCase (testCtx, name, description, glu::GLSL_VERSION_310_ES, exitingStages, activeStages)
6064 , m_isPrimaryCmdBuf (isPrimaryCmdBuf)
6065 , m_descriptorType (descriptorType)
6066 , m_shaderInterface (shaderInterface)
6067 , m_nonzeroViewOffset (((flags & FLAG_VIEW_OFFSET) != 0) ? (1u) : (0u))
6068 {
6069 }
6070
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const6071 std::string TexelBufferDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const
6072 {
6073 DE_UNREF(stage);
6074 return "#extension GL_EXT_texture_buffer : require\n";
6075 }
6076
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const6077 std::string TexelBufferDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const
6078 {
6079 DE_UNREF(stage);
6080
6081 const bool isUniform = isUniformDescriptorType(m_descriptorType);
6082 const char* const storageType = (isUniform) ? ("samplerBuffer ") : ("readonly imageBuffer ");
6083 const char* const formatQualifier = (isUniform) ? ("") : (", rgba8");
6084
6085 switch (m_shaderInterface)
6086 {
6087 case SHADER_INPUT_SINGLE_DESCRIPTOR:
6088 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBuffer;\n";
6089
6090 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6091 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBufferA;\n"
6092 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + formatQualifier + ") uniform highp " + storageType + " u_texelBufferB;\n";
6093
6094 case SHADER_INPUT_DESCRIPTOR_ARRAY:
6095 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBuffer[2];\n";
6096
6097 default:
6098 DE_FATAL("Impossible");
6099 return "";
6100 }
6101 }
6102
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const6103 std::string TexelBufferDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const
6104 {
6105 DE_UNREF(stage);
6106
6107 const char* const accessPostfixA = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("")
6108 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("A")
6109 : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[0]")
6110 : (DE_NULL);
6111 const char* const accessPostfixB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("")
6112 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("B")
6113 : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[1]")
6114 : (DE_NULL);
6115 const char* const fetchFunc = (isUniformDescriptorType(m_descriptorType)) ? ("texelFetch") : ("imageLoad");
6116 std::ostringstream buf;
6117
6118 buf << " if (quadrant_id == 0)\n"
6119 << " result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixA << ", " << TexelBufferInstanceBuffers::getFetchPos(0) << ");\n"
6120 << " else if (quadrant_id == 1)\n"
6121 << " result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixB << ", " << TexelBufferInstanceBuffers::getFetchPos(1) << ");\n"
6122 << " else if (quadrant_id == 2)\n"
6123 << " result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixA << ", " << TexelBufferInstanceBuffers::getFetchPos(2) << ");\n"
6124 << " else\n"
6125 << " result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixB << ", " << TexelBufferInstanceBuffers::getFetchPos(3) << ");\n";
6126
6127 return buf.str();
6128 }
6129
genNoAccessSource(void) const6130 std::string TexelBufferDescriptorCase::genNoAccessSource (void) const
6131 {
6132 return " if (quadrant_id == 1 || quadrant_id == 2)\n"
6133 " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
6134 " else\n"
6135 " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
6136 }
6137
createInstance(vkt::Context & context) const6138 vkt::TestInstance* TexelBufferDescriptorCase::createInstance (vkt::Context& context) const
6139 {
6140 verifyDriverSupport(context.getDeviceFeatures(), m_descriptorType, m_activeStages);
6141
6142 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
6143 {
6144 DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
6145 return new TexelBufferComputeInstance(context, m_descriptorType, m_shaderInterface, m_nonzeroViewOffset);
6146 }
6147 else
6148 return new TexelBufferRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_nonzeroViewOffset);
6149 }
6150
createShaderAccessImageTests(tcu::TestCaseGroup * group,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,ShaderInputInterface dimension,deUint32 resourceFlags)6151 void createShaderAccessImageTests (tcu::TestCaseGroup* group,
6152 bool isPrimaryCmdBuf,
6153 vk::VkDescriptorType descriptorType,
6154 vk::VkShaderStageFlags exitingStages,
6155 vk::VkShaderStageFlags activeStages,
6156 ShaderInputInterface dimension,
6157 deUint32 resourceFlags)
6158 {
6159 static const struct
6160 {
6161 vk::VkImageViewType viewType;
6162 const char* name;
6163 const char* description;
6164 deUint32 flags;
6165 } s_imageTypes[] =
6166 {
6167 { vk::VK_IMAGE_VIEW_TYPE_1D, "1d", "1D image view", 0u },
6168 { vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_mip", "1D image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
6169 { vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_slice", "1D image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE },
6170
6171 { vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array", "1D array image view", 0u },
6172 { vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_mip", "1D array image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
6173 { vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_slice", "1D array image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE },
6174
6175 { vk::VK_IMAGE_VIEW_TYPE_2D, "2d", "2D image view", 0u },
6176 { vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_mip", "2D image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
6177 { vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_slice", "2D image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE },
6178
6179 { vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array", "2D array image view", 0u },
6180 { vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_mip", "2D array image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
6181 { vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_slice", "2D array image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE },
6182
6183 { vk::VK_IMAGE_VIEW_TYPE_3D, "3d", "3D image view", 0u },
6184 { vk::VK_IMAGE_VIEW_TYPE_3D, "3d_base_mip", "3D image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
6185 // no 3d array textures
6186
6187 { vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube", "Cube image view", 0u },
6188 { vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_mip", "Cube image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
6189 { vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_slice", "Cube image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE },
6190
6191 { vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array", "Cube image view", 0u },
6192 { vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_mip", "Cube image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
6193 { vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_slice", "Cube image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE },
6194 };
6195
6196 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++ndx)
6197 {
6198 // never overlap
6199 DE_ASSERT((s_imageTypes[ndx].flags & resourceFlags) == 0u);
6200
6201 // SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS only supported in VK_DESCRIPTOR_TYPE_SAMPLER on graphics shaders for now
6202 if (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS &&
6203 (descriptorType != vk::VK_DESCRIPTOR_TYPE_SAMPLER || activeStages == vk::VK_SHADER_STAGE_COMPUTE_BIT))
6204 continue;
6205
6206 group->addChild(new ImageDescriptorCase(group->getTestContext(),
6207 s_imageTypes[ndx].name,
6208 s_imageTypes[ndx].description,
6209 isPrimaryCmdBuf,
6210 descriptorType,
6211 exitingStages,
6212 activeStages,
6213 dimension,
6214 s_imageTypes[ndx].viewType,
6215 s_imageTypes[ndx].flags | resourceFlags));
6216 }
6217 }
6218
createShaderAccessTexelBufferTests(tcu::TestCaseGroup * group,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,ShaderInputInterface dimension,deUint32 resourceFlags)6219 void createShaderAccessTexelBufferTests (tcu::TestCaseGroup* group,
6220 bool isPrimaryCmdBuf,
6221 vk::VkDescriptorType descriptorType,
6222 vk::VkShaderStageFlags exitingStages,
6223 vk::VkShaderStageFlags activeStages,
6224 ShaderInputInterface dimension,
6225 deUint32 resourceFlags)
6226 {
6227 DE_ASSERT(resourceFlags == 0);
6228 DE_UNREF(resourceFlags);
6229
6230 static const struct
6231 {
6232 const char* name;
6233 const char* description;
6234 deUint32 flags;
6235 } s_texelBufferTypes[] =
6236 {
6237 { "offset_zero", "View offset is zero", 0u },
6238 { "offset_nonzero", "View offset is non-zero", TexelBufferDescriptorCase::FLAG_VIEW_OFFSET },
6239 };
6240
6241 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_texelBufferTypes); ++ndx)
6242 {
6243 if (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS)
6244 continue;
6245
6246 group->addChild(new TexelBufferDescriptorCase(group->getTestContext(),
6247 s_texelBufferTypes[ndx].name,
6248 s_texelBufferTypes[ndx].description,
6249 isPrimaryCmdBuf,
6250 descriptorType,
6251 exitingStages,
6252 activeStages,
6253 dimension,
6254 s_texelBufferTypes[ndx].flags));
6255 }
6256 }
6257
createShaderAccessBufferTests(tcu::TestCaseGroup * group,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,ShaderInputInterface dimension,deUint32 resourceFlags)6258 void createShaderAccessBufferTests (tcu::TestCaseGroup* group,
6259 bool isPrimaryCmdBuf,
6260 vk::VkDescriptorType descriptorType,
6261 vk::VkShaderStageFlags exitingStages,
6262 vk::VkShaderStageFlags activeStages,
6263 ShaderInputInterface dimension,
6264 deUint32 resourceFlags)
6265 {
6266 DE_ASSERT(resourceFlags == 0u);
6267 DE_UNREF(resourceFlags);
6268
6269 static const struct
6270 {
6271 const char* name;
6272 const char* description;
6273 bool isForDynamicCases;
6274 deUint32 flags;
6275 } s_bufferTypes[] =
6276 {
6277 { "offset_view_zero", "View offset is zero", false, 0u },
6278 { "offset_view_nonzero", "View offset is non-zero", false, BufferDescriptorCase::FLAG_VIEW_OFFSET },
6279
6280 { "offset_view_zero_dynamic_zero", "View offset is zero, dynamic offset is zero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO },
6281 { "offset_view_zero_dynamic_nonzero", "View offset is zero, dynamic offset is non-zero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO },
6282 { "offset_view_nonzero_dynamic_zero", "View offset is non-zero, dynamic offset is zero", true, BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO },
6283 { "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 },
6284 };
6285
6286 const bool isDynamicCase = isDynamicDescriptorType(descriptorType);
6287
6288 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_bufferTypes); ++ndx)
6289 {
6290 if (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS)
6291 continue;
6292
6293 if (isDynamicCase == s_bufferTypes[ndx].isForDynamicCases)
6294 group->addChild(new BufferDescriptorCase(group->getTestContext(),
6295 s_bufferTypes[ndx].name,
6296 s_bufferTypes[ndx].description,
6297 isPrimaryCmdBuf,
6298 descriptorType,
6299 exitingStages,
6300 activeStages,
6301 dimension,
6302 s_bufferTypes[ndx].flags));
6303 }
6304 }
6305
6306 } // anonymous
6307
createShaderAccessTests(tcu::TestContext & testCtx)6308 tcu::TestCaseGroup* createShaderAccessTests (tcu::TestContext& testCtx)
6309 {
6310 static const struct
6311 {
6312 const bool isPrimary;
6313 const char* name;
6314 const char* description;
6315 } s_bindTypes[] =
6316 {
6317 { true, "primary_cmd_buf", "Bind in primary command buffer" },
6318 { false, "secondary_cmd_buf", "Bind in secondary command buffer" },
6319 };
6320 static const struct
6321 {
6322 const vk::VkDescriptorType descriptorType;
6323 const char* name;
6324 const char* description;
6325 deUint32 flags;
6326 } s_descriptorTypes[] =
6327 {
6328 { vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_mutable", "VK_DESCRIPTOR_TYPE_SAMPLER with mutable sampler", 0u },
6329 { vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_immutable", "VK_DESCRIPTOR_TYPE_SAMPLER with immutable sampler", RESOURCE_FLAG_IMMUTABLE_SAMPLER },
6330 { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_mutable", "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with mutable sampler", 0u },
6331 { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_immutable", "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with immutable sampler", RESOURCE_FLAG_IMMUTABLE_SAMPLER },
6332 // \note No way to access SAMPLED_IMAGE without a sampler
6333 //{ vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "sampled_image", "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE", 0u },
6334 { vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, "storage_image", "VK_DESCRIPTOR_TYPE_STORAGE_IMAGE", 0u },
6335 { vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, "uniform_texel_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER", 0u },
6336 { vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, "storage_texel_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER", 0u },
6337 { vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "uniform_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER", 0u },
6338 { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, "storage_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER", 0u },
6339 { vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, "uniform_buffer_dynamic", "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC", 0u },
6340 { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "storage_buffer_dynamic", "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC", 0u },
6341 };
6342 static const struct
6343 {
6344 const char* name;
6345 const char* description;
6346 vk::VkShaderStageFlags existingStages; //!< stages that exists
6347 vk::VkShaderStageFlags activeStages; //!< stages that access resource
6348 bool supportsSecondaryCmdBufs;
6349 } s_shaderStages[] =
6350 {
6351 {
6352 "no_access",
6353 "No accessing stages",
6354 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6355 0u,
6356 true,
6357 },
6358 {
6359 "vertex",
6360 "Vertex stage",
6361 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6362 vk::VK_SHADER_STAGE_VERTEX_BIT,
6363 true,
6364 },
6365 {
6366 "tess_ctrl",
6367 "Tessellation control stage",
6368 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,
6369 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
6370 true,
6371 },
6372 {
6373 "tess_eval",
6374 "Tessellation evaluation stage",
6375 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,
6376 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
6377 true,
6378 },
6379 {
6380 "geometry",
6381 "Geometry stage",
6382 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6383 vk::VK_SHADER_STAGE_GEOMETRY_BIT,
6384 true,
6385 },
6386 {
6387 "fragment",
6388 "Fragment stage",
6389 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6390 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6391 true,
6392 },
6393 {
6394 "compute",
6395 "Compute stage",
6396 vk::VK_SHADER_STAGE_COMPUTE_BIT,
6397 vk::VK_SHADER_STAGE_COMPUTE_BIT,
6398 false,
6399 },
6400 {
6401 "vertex_fragment",
6402 "Vertex and fragment stages",
6403 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6404 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6405 true,
6406 },
6407 };
6408 static const struct
6409 {
6410 ShaderInputInterface dimension;
6411 const char* name;
6412 const char* description;
6413 } s_variableDimensions[] =
6414 {
6415 { SHADER_INPUT_SINGLE_DESCRIPTOR, "single_descriptor", "Single descriptor" },
6416 { SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS, "multiple_contiguous_descriptors", "Multiple descriptors" },
6417 { SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS, "multiple_discontiguous_descriptors", "Multiple descriptors" },
6418 { SHADER_INPUT_DESCRIPTOR_ARRAY, "descriptor_array", "Descriptor array" },
6419 };
6420
6421 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_access", "Access resource via descriptor in a single descriptor set"));
6422
6423 // .primary_cmd_buf...
6424 for (int bindTypeNdx = 0; bindTypeNdx < DE_LENGTH_OF_ARRAY(s_bindTypes); ++bindTypeNdx)
6425 {
6426 de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, s_bindTypes[bindTypeNdx].name, s_bindTypes[bindTypeNdx].description));
6427
6428 // .sampler, .combined_image_sampler, other resource types ...
6429 for (int descriptorNdx = 0; descriptorNdx < DE_LENGTH_OF_ARRAY(s_descriptorTypes); ++descriptorNdx)
6430 {
6431 de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(testCtx, s_descriptorTypes[descriptorNdx].name, s_descriptorTypes[descriptorNdx].description));
6432
6433 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(s_shaderStages); ++stageNdx)
6434 {
6435 if (s_bindTypes[bindTypeNdx].isPrimary || s_shaderStages[stageNdx].supportsSecondaryCmdBufs)
6436 {
6437 de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, s_shaderStages[stageNdx].name, s_shaderStages[stageNdx].description));
6438
6439 for (int dimensionNdx = 0; dimensionNdx < DE_LENGTH_OF_ARRAY(s_variableDimensions); ++dimensionNdx)
6440 {
6441 de::MovePtr<tcu::TestCaseGroup> dimensionGroup(new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name, s_variableDimensions[dimensionNdx].description));
6442 void (*createTestsFunc)(tcu::TestCaseGroup* group,
6443 bool isPrimaryCmdBuf,
6444 vk::VkDescriptorType descriptorType,
6445 vk::VkShaderStageFlags existingStages,
6446 vk::VkShaderStageFlags activeStages,
6447 ShaderInputInterface dimension,
6448 deUint32 resourceFlags);
6449
6450 switch (s_descriptorTypes[descriptorNdx].descriptorType)
6451 {
6452 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
6453 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
6454 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
6455 createTestsFunc = createShaderAccessImageTests;
6456 break;
6457
6458 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
6459 case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
6460 createTestsFunc = createShaderAccessTexelBufferTests;
6461 break;
6462
6463 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
6464 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
6465 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
6466 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
6467 createTestsFunc = createShaderAccessBufferTests;
6468 break;
6469
6470 default:
6471 createTestsFunc = DE_NULL;
6472 DE_FATAL("Impossible");
6473 }
6474
6475 if (createTestsFunc)
6476 {
6477 createTestsFunc(dimensionGroup.get(),
6478 s_bindTypes[bindTypeNdx].isPrimary,
6479 s_descriptorTypes[descriptorNdx].descriptorType,
6480 s_shaderStages[stageNdx].existingStages,
6481 s_shaderStages[stageNdx].activeStages,
6482 s_variableDimensions[dimensionNdx].dimension,
6483 s_descriptorTypes[descriptorNdx].flags);
6484 }
6485 else
6486 DE_FATAL("Impossible");
6487
6488 stageGroup->addChild(dimensionGroup.release());
6489 }
6490
6491 typeGroup->addChild(stageGroup.release());
6492 }
6493 }
6494
6495 bindGroup->addChild(typeGroup.release());
6496 }
6497
6498 group->addChild(bindGroup.release());
6499 }
6500
6501 return group.release();
6502 }
6503
6504 } // BindingModel
6505 } // vkt
6506