1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 The Khronos Group Inc.
6 * Copyright (c) 2016 The Android Open Source Project
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief SPIR-V Assembly Tests for PhysicalStorageBuffer.
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktSpvAsmPhysicalStorageBufferPointerTests.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vkBarrierUtil.hpp"
29 #include "vkBuilderUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "deSharedPtr.hpp"
37 #include "deUniquePtr.hpp"
38 #include "tcuTextureUtil.hpp"
39 #include "tcuVectorUtil.hpp"
40
41 #include <iterator>
42
43 using namespace vk;
44 using de::MovePtr;
45 using de::SharedPtr;
46
47 namespace vkt
48 {
49 namespace SpirVAssembly
50 {
51
52 namespace
53 {
54
55 enum class PassMethod
56 {
57 PUSH_CONSTANTS,
58 PUSH_CONSTANTS_FUNCTION,
59 VERTEX_IN_OUT_IN,
60 ADDRESSES_IN_SSBO
61 };
62
63 struct TestParams
64 {
65 PassMethod method;
66 deUint32 elements;
67 };
68
69 typedef SharedPtr<const TestParams> TestParamsPtr;
70
71 namespace ut
72 {
73
74 class Buffer
75 {
76 public:
77 Buffer (Context& ctx, VkBufferUsageFlags usage, VkDeviceSize size, bool address = false);
78 Buffer (const Buffer& src);
79
getBuffer(void) const80 VkBuffer getBuffer (void) const { return **m_buffer; }
getSize(void) const81 VkDeviceSize getSize (void) const { return m_size; }
getData(void) const82 void* getData (void) const { return (*m_bufferMemory)->getHostPtr(); }
83 deUint64 getDeviceAddress(void) const;
84 void zero (bool flushAfter = false);
85 void flush (void);
86 void invalidate (void);
87
88 protected:
89 Context& m_context;
90 const VkDeviceSize m_size;
91 const bool m_address;
92 SharedPtr<Move<VkBuffer>> m_buffer;
93 SharedPtr<MovePtr<Allocation>> m_bufferMemory;
94 };
95
96 template<class X> class TypedBuffer : public Buffer
97 {
98 public:
99 TypedBuffer (Context& ctx,
100 VkBufferUsageFlags usage,
101 deUint32 nelements,
102 bool address = false);
103 TypedBuffer (Context& ctx,
104 VkBufferUsageFlags usage,
105 std::initializer_list<X> items,
106 bool address = false);
107 TypedBuffer (const TypedBuffer& src);
108 TypedBuffer (const Buffer& src);
109
getElements(void) const110 deUint32 getElements (void) const { return m_elements; }
getData(void) const111 X* getData (void) const { return reinterpret_cast<X*>(Buffer::getData()); }
112 void iota (X start, bool flushAfter = false);
113 X& operator[] (deUint32 at);
114
115 struct iterator;
begin()116 iterator begin () { return iterator(getData()); }
end()117 iterator end () { return iterator(&getData()[m_elements]); }
118
119 private:
120 const deUint32 m_elements;
121 };
122
123 class Image
124 {
125 public:
126 Image (Context& ctx,
127 deUint32 width,
128 deUint32 height,
129 VkFormat format);
130 Image (const Image&) = delete;
131 Image (Image&&) = delete;
132
133 Move<VkRenderPass> createRenderPass (void) const;
134 Move<VkFramebuffer> createFramebuffer (VkRenderPass rp) const;
135
136 template<class X> TypedBuffer<X> getBuffer (void);
137 void downloadAfterDraw (VkCommandBuffer cmdBuffer);
138
139 private:
140 Context& m_context;
141 const deUint32 m_width;
142 const deUint32 m_height;
143 const VkFormat m_format;
144 VkImageLayout m_layout;
145 Buffer m_buffer;
146
147 Move<VkImage> m_image;
148 Move<VkImageView> m_view;
149 de::MovePtr<Allocation> m_imageMemory;
150 };
151
makeShared(Move<X> move)152 template<class X> SharedPtr<Move<X>> makeShared(Move<X> move)
153 {
154 return SharedPtr<Move<X>>(new Move<X>(move));
155 }
156
makeShared(MovePtr<X> move)157 template<class X> SharedPtr<MovePtr<X>> makeShared(MovePtr<X> move)
158 {
159 return SharedPtr<MovePtr<X>>(new MovePtr<X>(move));
160 }
161
Buffer(Context & ctx,VkBufferUsageFlags usage,VkDeviceSize size,bool address)162 Buffer::Buffer (Context& ctx, VkBufferUsageFlags usage, VkDeviceSize size, bool address)
163 : m_context (ctx)
164 , m_size (size)
165 , m_address (address)
166 {
167 const DeviceInterface& vki = m_context.getDeviceInterface();
168 const VkDevice dev = m_context.getDevice();
169 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
170 Allocator& allocator = m_context.getDefaultAllocator();
171
172 const VkBufferUsageFlags bufferUsageFlags = address ? (usage | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) : usage;
173 const MemoryRequirement requirements = MemoryRequirement::Coherent | MemoryRequirement::HostVisible | (address ? MemoryRequirement::DeviceAddress : MemoryRequirement::Any);
174
175 const VkBufferCreateInfo bufferCreateInfo
176 {
177 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
178 DE_NULL, // const void* pNext;
179 0u, // VkBufferCreateFlags flags;
180 size, // VkDeviceSize size;
181 bufferUsageFlags, // VkBufferUsageFlags usage;
182 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
183 1u, // deUint32 queueFamilyIndexCount;
184 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
185 };
186
187 m_buffer = makeShared(createBuffer(vki, dev, &bufferCreateInfo));
188 m_bufferMemory = makeShared(allocator.allocate(getBufferMemoryRequirements(vki, dev, **m_buffer), requirements));
189
190 VK_CHECK(vki.bindBufferMemory(dev, **m_buffer, (*m_bufferMemory)->getMemory(), (*m_bufferMemory)->getOffset()));
191 }
192
Buffer(const Buffer & src)193 Buffer::Buffer (const Buffer& src)
194 : m_context (src.m_context)
195 , m_size (src.m_size)
196 , m_address (src.m_address)
197 , m_buffer (src.m_buffer)
198 , m_bufferMemory(src.m_bufferMemory)
199 {
200 }
201
getDeviceAddress(void) const202 deUint64 Buffer::getDeviceAddress (void) const
203 {
204 DE_ASSERT(m_address);
205
206 const DeviceInterface& vki = m_context.getDeviceInterface();
207 const VkDevice dev = m_context.getDevice();
208 const VkBufferDeviceAddressInfo info
209 {
210 VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, // VkStructureType sType;
211 DE_NULL, // const void* pNext;
212 **m_buffer // VkBuffer buffer;
213 };
214
215 return vki.getBufferDeviceAddress(dev, &info);
216 }
217
zero(bool flushAfter)218 void Buffer::zero (bool flushAfter)
219 {
220 deMemset(getData(), 0, static_cast<size_t>(m_size));
221 if (flushAfter) flush();
222 }
223
flush(void)224 void Buffer::flush (void)
225 {
226 const DeviceInterface& vki = m_context.getDeviceInterface();
227 const VkDevice dev = m_context.getDevice();
228 flushAlloc(vki, dev, **m_bufferMemory);
229 }
230
invalidate(void)231 void Buffer::invalidate (void)
232 {
233 const DeviceInterface& vki = m_context.getDeviceInterface();
234 const VkDevice dev = m_context.getDevice();
235 invalidateAlloc(vki, dev, **m_bufferMemory);
236 }
237
238 template<class X> struct TypedBuffer<X>::iterator
239 {
240 typedef std::forward_iterator_tag iterator_category;
241 typedef std::ptrdiff_t difference_type;
242 typedef X value_type;
243 typedef X& reference;
244 typedef X* pointer;
245
iteratorvkt::SpirVAssembly::__anon1f7687710111::ut::TypedBuffer::iterator246 iterator (pointer p) : m_p(p) { DE_ASSERT(p); }
operator *vkt::SpirVAssembly::__anon1f7687710111::ut::TypedBuffer::iterator247 reference operator* () { return *m_p; }
operator ++vkt::SpirVAssembly::__anon1f7687710111::ut::TypedBuffer::iterator248 iterator& operator++ () { ++m_p; return *this; }
operator ++vkt::SpirVAssembly::__anon1f7687710111::ut::TypedBuffer::iterator249 iterator operator++ (int) { return iterator(m_p++); }
operator ==vkt::SpirVAssembly::__anon1f7687710111::ut::TypedBuffer::iterator250 bool operator== (const iterator& other) const { return (m_p == other.m_p); }
operator !=vkt::SpirVAssembly::__anon1f7687710111::ut::TypedBuffer::iterator251 bool operator!= (const iterator& other) const { return (m_p != other.m_p); }
252
253 private:
254 pointer m_p;
255 };
256
TypedBuffer(Context & ctx,VkBufferUsageFlags usage,deUint32 nelements,bool address)257 template<class X> TypedBuffer<X>::TypedBuffer (Context& ctx, VkBufferUsageFlags usage, deUint32 nelements, bool address)
258 : Buffer (ctx, usage, (nelements * sizeof(X)), address)
259 , m_elements (nelements)
260 {
261 }
262
TypedBuffer(Context & ctx,VkBufferUsageFlags usage,std::initializer_list<X> items,bool address)263 template<class X> TypedBuffer<X>::TypedBuffer (Context& ctx, VkBufferUsageFlags usage, std::initializer_list<X> items, bool address)
264 : Buffer (ctx, usage, (items.size() * sizeof(X)), address)
265 , m_elements (static_cast<deUint32>(items.size()))
266 {
267 std::copy(items.begin(), items.end(), begin());
268 }
269
TypedBuffer(const TypedBuffer & src)270 template<class X> TypedBuffer<X>::TypedBuffer (const TypedBuffer& src)
271 : Buffer (src)
272 , m_elements(src.m_elements)
273 {
274 }
275
TypedBuffer(const Buffer & src)276 template<class X> TypedBuffer<X>::TypedBuffer (const Buffer& src)
277 : Buffer (src)
278 , m_elements(static_cast<deUint32>(m_size/sizeof(X)))
279 {
280 }
281
iota(X start,bool flushAfter)282 template<class X> void TypedBuffer<X>::iota (X start, bool flushAfter)
283 {
284 X* data = getData();
285 for (deUint32 i = 0; i < m_elements; ++i)
286 data[i] = start++;
287 if (flushAfter) flush();
288 }
289
operator [](deUint32 at)290 template<class X> X& TypedBuffer<X>::operator[] (deUint32 at)
291 {
292 DE_ASSERT(at < m_elements);
293 return getData()[at];
294 }
295
Image(Context & ctx,deUint32 width,deUint32 height,VkFormat format)296 Image::Image (Context& ctx, deUint32 width, deUint32 height, VkFormat format)
297 : m_context (ctx)
298 , m_width (width)
299 , m_height (height)
300 , m_format (format)
301 , m_layout (VK_IMAGE_LAYOUT_UNDEFINED)
302 , m_buffer (ctx, (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT), (m_width * m_height * vk::mapVkFormat(m_format).getPixelSize()), false)
303 {
304 const DeviceInterface& vki = m_context.getDeviceInterface();
305 const VkDevice dev = m_context.getDevice();
306 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
307 const VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
308 const VkImageSubresourceRange viewResourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
309 Allocator& allocator = m_context.getDefaultAllocator();
310
311 const VkImageCreateInfo imageCreateInfo =
312 {
313 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
314 DE_NULL, // const void* pNext;
315 0u, // VkImageCreateFlags flags;
316 VK_IMAGE_TYPE_2D, // VkImageType imageType;
317 m_format, // VkFormat format;
318 { m_width, m_height, 1u }, // VkExtent3D extent;
319 1u, // deUint32 mipLevels;
320 1u, // deUint32 arrayLayers;
321 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
322 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
323 imageUsageFlags, // VkImageUsageFlags usage;
324 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
325 1u, // deUint32 queueFamilyIndexCount;
326 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
327 m_layout // VkImageLayout initialLayout;
328 };
329
330 m_image = createImage(vki, dev, &imageCreateInfo);
331
332 m_imageMemory = allocator.allocate(getImageMemoryRequirements(vki, dev, *m_image), MemoryRequirement::Any);
333 VK_CHECK(vki.bindImageMemory(dev, *m_image, m_imageMemory->getMemory(), m_imageMemory->getOffset()));
334
335 m_view = makeImageView(vki, dev, *m_image, VK_IMAGE_VIEW_TYPE_2D, m_format, viewResourceRange);
336 }
337
getBuffer(void)338 template<class X> TypedBuffer<X> Image::getBuffer (void)
339 {
340 m_buffer.invalidate();
341 return TypedBuffer<X>(m_buffer);
342 }
343
createRenderPass(void) const344 Move<VkRenderPass> Image::createRenderPass (void) const
345 {
346 const DeviceInterface& vki = m_context.getDeviceInterface();
347 const VkDevice dev = m_context.getDevice();
348
349 const VkAttachmentDescription attachmentDescription =
350 {
351 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
352 m_format, // VkFormat format
353 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
354 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
355 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
356 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
357 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
358 m_layout, // VkImageLayout initialLayout
359 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
360 };
361
362 const VkAttachmentReference attachmentReference =
363 {
364 0u, // deUint32 attachment
365 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout
366 };
367
368 const VkSubpassDescription subpassDescription =
369 {
370 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
371 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
372 0u, // deUint32 inputAttachmentCount
373 DE_NULL, // const VkAttachmentReference* pInputAttachments
374 1u, // deUint32 colorAttachmentCount
375 &attachmentReference, // const VkAttachmentReference* pColorAttachments
376 DE_NULL, // const VkAttachmentReference* pResolveAttachments
377 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
378 0u, // deUint32 preserveAttachmentCount
379 DE_NULL // const deUint32* pPreserveAttachments
380 };
381
382 const VkRenderPassCreateInfo renderPassInfo =
383 {
384 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
385 DE_NULL, // const void* pNext
386 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
387 1u, // deUint32 attachmentCount
388 &attachmentDescription, // const VkAttachmentDescription* pAttachments
389 1u, // deUint32 subpassCount
390 &subpassDescription, // const VkSubpassDescription* pSubpasses
391 0u, // deUint32 dependencyCount
392 DE_NULL // const VkSubpassDependency* pDependencies
393 };
394
395 return vk::createRenderPass(vki, dev, &renderPassInfo);
396 }
397
createFramebuffer(VkRenderPass rp) const398 Move<VkFramebuffer> Image::createFramebuffer (VkRenderPass rp) const
399 {
400 const DeviceInterface& vki = m_context.getDeviceInterface();
401 const VkDevice dev = m_context.getDevice();
402
403 return makeFramebuffer(vki, dev, rp, 1u, &m_view.get(), m_width, m_height, 1u);
404 }
405
downloadAfterDraw(VkCommandBuffer cmdBuffer)406 void Image::downloadAfterDraw (VkCommandBuffer cmdBuffer)
407 {
408 const DeviceInterface& vki = m_context.getDeviceInterface();
409 vk::copyImageToBuffer(vki, cmdBuffer, *m_image, m_buffer.getBuffer(), { deInt32(m_width), deInt32(m_height) });
410 m_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
411 }
412
413 } // ut
414
415 class SpvAsmPhysicalStorageBufferTestInstance : public TestInstance
416 {
417 public:
SpvAsmPhysicalStorageBufferTestInstance(Context & ctx)418 SpvAsmPhysicalStorageBufferTestInstance (Context& ctx)
419 : TestInstance (ctx)
420 {
421 }
422 };
423
424 class SpvAsmPhysicalStorageBufferVertexInOutInTestInstance : public SpvAsmPhysicalStorageBufferTestInstance
425 {
426 public:
SpvAsmPhysicalStorageBufferVertexInOutInTestInstance(Context & ctx,const TestParamsPtr params)427 SpvAsmPhysicalStorageBufferVertexInOutInTestInstance (Context& ctx,
428 const TestParamsPtr params)
429 : SpvAsmPhysicalStorageBufferTestInstance (ctx)
430 , m_params (params)
431 {
432 }
433 tcu::TestStatus iterate (void);
434 static void initPrograms (vk::SourceCollections& programCollection,
435 const TestParamsPtr params);
436 struct alignas(16) Attribute
437 {
438 tcu::Vec4 position;
439 deUint64 address;
440 };
441 ut::TypedBuffer<tcu::Vec4> prepareColorBuffer (bool flushAfter = true) const;
442 ut::TypedBuffer<Attribute> prepareVertexAttributes (deUint64 address) const;
443 Move<VkPipeline> createGraphicsPipeline (VkPipelineLayout pipelineLayout,
444 VkRenderPass renderPass,
445 VkShaderModule vertexModule,
446 VkShaderModule fragmentModule) const;
447
448 private:
449 const TestParamsPtr m_params;
450 };
451
452 class SpvAsmPhysicalStorageBufferPushConstantsTestInstance : public SpvAsmPhysicalStorageBufferTestInstance
453 {
454 public:
SpvAsmPhysicalStorageBufferPushConstantsTestInstance(Context & ctx,const TestParamsPtr params)455 SpvAsmPhysicalStorageBufferPushConstantsTestInstance (Context& ctx,
456 const TestParamsPtr params)
457 : SpvAsmPhysicalStorageBufferTestInstance (ctx)
458 , m_params (params)
459 {
460 }
461 tcu::TestStatus iterate (void);
462 static void initPrograms (vk::SourceCollections& programCollection,
463 const TestParamsPtr params);
464
465 private:
466 const TestParamsPtr m_params;
467 };
468
469 class SpvAsmPhysicalStorageBufferAddrsInSSBOTestInstance : public SpvAsmPhysicalStorageBufferTestInstance
470 {
471 public:
SpvAsmPhysicalStorageBufferAddrsInSSBOTestInstance(Context & ctx,const TestParamsPtr params)472 SpvAsmPhysicalStorageBufferAddrsInSSBOTestInstance (Context& ctx,
473 const TestParamsPtr params)
474 : SpvAsmPhysicalStorageBufferTestInstance (ctx)
475 , m_params (params)
476 {
477 }
478 tcu::TestStatus iterate (void);
479 static void initPrograms (vk::SourceCollections& programCollection,
480 const TestParamsPtr params);
481
482 private:
483 const TestParamsPtr m_params;
484 };
485
486 class SpvAsmPhysicalStorageBufferTestCase : public TestCase
487 {
488 public:
SpvAsmPhysicalStorageBufferTestCase(tcu::TestContext & testCtx,const std::string & name,const TestParamsPtr params)489 SpvAsmPhysicalStorageBufferTestCase (tcu::TestContext& testCtx,
490 const std::string& name,
491 const TestParamsPtr params)
492 : TestCase (testCtx, name, std::string())
493 , m_params (params)
494 {
495 }
496 void checkSupport (Context& context) const;
497 void initPrograms (vk::SourceCollections& programCollection) const;
498 TestInstance* createInstance (Context& ctx) const;
499
500 private:
501 const TestParamsPtr m_params;
502 };
503
checkSupport(Context & context) const504 void SpvAsmPhysicalStorageBufferTestCase::checkSupport (Context& context) const
505 {
506 context.requireInstanceFunctionality(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); // "VK_KHR_get_physical_device_properties2"
507
508 if (!context.isBufferDeviceAddressSupported())
509 TCU_THROW(NotSupportedError, "Request physical storage buffer feature not supported");
510
511 if (m_params->method == PassMethod::ADDRESSES_IN_SSBO)
512 {
513 if (!context.getDeviceFeatures().shaderInt64)
514 TCU_THROW(NotSupportedError, "Int64 not supported");
515 }
516
517 if (m_params->method == PassMethod::VERTEX_IN_OUT_IN)
518 {
519 if (!context.getDeviceFeatures().shaderInt64)
520 TCU_THROW(NotSupportedError, "Int64 not supported");
521
522 VkFormatProperties2 properties { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, DE_NULL, {} };
523 context.getInstanceInterface().getPhysicalDeviceFormatProperties2(context.getPhysicalDevice(), VK_FORMAT_R64_UINT, &properties);
524 if ((properties.formatProperties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)
525 TCU_THROW(NotSupportedError, "VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT not supported");
526 }
527 }
528
createInstance(Context & ctx) const529 TestInstance* SpvAsmPhysicalStorageBufferTestCase::createInstance (Context& ctx) const
530 {
531 switch (m_params->method)
532 {
533 case PassMethod::PUSH_CONSTANTS:
534 case PassMethod::PUSH_CONSTANTS_FUNCTION:
535 return new SpvAsmPhysicalStorageBufferPushConstantsTestInstance(ctx, m_params);
536
537 case PassMethod::VERTEX_IN_OUT_IN:
538 return new SpvAsmPhysicalStorageBufferVertexInOutInTestInstance(ctx, m_params);
539
540 case PassMethod::ADDRESSES_IN_SSBO:
541 return new SpvAsmPhysicalStorageBufferAddrsInSSBOTestInstance(ctx, m_params);
542 }
543
544 DE_ASSERT(DE_FALSE);
545 return DE_NULL;
546 }
547
initPrograms(vk::SourceCollections & programCollection) const548 void SpvAsmPhysicalStorageBufferTestCase::initPrograms (vk::SourceCollections& programCollection) const
549 {
550 switch (m_params->method)
551 {
552 case PassMethod::PUSH_CONSTANTS:
553 case PassMethod::PUSH_CONSTANTS_FUNCTION:
554 SpvAsmPhysicalStorageBufferPushConstantsTestInstance::initPrograms(programCollection, m_params);
555 break;
556
557 case PassMethod::VERTEX_IN_OUT_IN:
558 SpvAsmPhysicalStorageBufferVertexInOutInTestInstance::initPrograms(programCollection, m_params);
559 break;
560
561 case PassMethod::ADDRESSES_IN_SSBO:
562 SpvAsmPhysicalStorageBufferAddrsInSSBOTestInstance::initPrograms(programCollection, m_params);
563 break;
564 }
565 }
566
initPrograms(SourceCollections & programCollection,const TestParamsPtr params)567 void SpvAsmPhysicalStorageBufferVertexInOutInTestInstance::initPrograms (SourceCollections &programCollection, const TestParamsPtr params)
568 {
569 DE_UNREF(params);
570
571 const std::string vert(R"(
572 OpCapability Shader
573 OpCapability PhysicalStorageBufferAddresses
574
575 OpExtension "SPV_KHR_physical_storage_buffer"
576 OpMemoryModel PhysicalStorageBuffer64 GLSL450
577
578 OpEntryPoint Vertex %vert "main" %gl_PerVertex %in_pos %out_idx %gl_VertexIndex %in_addr %out_addr
579
580 OpDecorate %PerVertex Block
581 OpDecorate %gl_VertexIndex BuiltIn VertexIndex
582 OpDecorate %in_pos Location 0
583 OpDecorate %in_addr Location 1
584 OpDecorate %in_addr RestrictPointerEXT
585 OpDecorate %out_addr RestrictPointerEXT
586 OpDecorate %out_idx Location 0
587 OpDecorate %out_addr Location 1
588
589 OpMemberDecorate %PerVertex 0 BuiltIn Position
590 OpMemberDecorate %PerVertex 1 BuiltIn PointSize
591 OpMemberDecorate %PerVertex 2 BuiltIn ClipDistance
592 OpMemberDecorate %PerVertex 3 BuiltIn CullDistance
593
594 OpDecorate %srta Block
595 OpMemberDecorate %srta 0 Offset 0
596
597 OpDecorate %rta ArrayStride 16
598
599 %void = OpTypeVoid
600 %voidf = OpTypeFunction %void
601
602 %int = OpTypeInt 32 1
603 %flt = OpTypeFloat 32
604 %vec4 = OpTypeVector %flt 4
605 %rta = OpTypeRuntimeArray %vec4
606
607 %zero = OpConstant %int 0
608 %one = OpConstant %int 1
609
610 %srta = OpTypeStruct %rta
611 %srta_psb = OpTypePointer PhysicalStorageBuffer %srta
612 %srta_psb_in = OpTypePointer Input %srta_psb
613 %srta_psb_out = OpTypePointer Output %srta_psb
614 %in_addr = OpVariable %srta_psb_in Input
615 %out_addr = OpVariable %srta_psb_out Output
616
617 %vec4_in = OpTypePointer Input %vec4
618 %vec4_out = OpTypePointer Output %vec4
619 %vec4_psb = OpTypePointer PhysicalStorageBuffer %vec4
620 %in_pos = OpVariable %vec4_in Input
621
622 %int_in = OpTypePointer Input %int
623 %int_out = OpTypePointer Output %int
624 %gl_VertexIndex = OpVariable %int_in Input
625 %out_idx = OpVariable %int_out Output
626
627 %flt_arr_1 = OpTypeArray %flt %one
628 %PerVertex = OpTypeStruct %vec4 %flt %flt_arr_1 %flt_arr_1
629 %pv_out = OpTypePointer Output %PerVertex
630 %gl_PerVertex = OpVariable %pv_out Output
631
632
633 %vert = OpFunction %void None %voidf
634 %vert_begin = OpLabel
635
636 %vpos = OpLoad %vec4 %in_pos
637 %gl_Position = OpAccessChain %vec4_out %gl_PerVertex %zero
638 OpStore %gl_Position %vpos
639
640 %vidx = OpLoad %int %gl_VertexIndex
641 OpStore %out_idx %vidx
642
643 %vaddr = OpLoad %srta_psb %in_addr Aligned 8
644 OpStore %out_addr %vaddr
645
646 OpReturn
647 OpFunctionEnd
648 )");
649
650 const std::string frag(R"(
651 OpCapability Shader
652 OpCapability PhysicalStorageBufferAddresses
653
654 OpExtension "SPV_KHR_physical_storage_buffer"
655 OpMemoryModel PhysicalStorageBuffer64 GLSL450
656
657 OpEntryPoint Fragment %frag "main" %in_idx %in_addr %dEQP_FragColor
658 OpExecutionMode %frag OriginUpperLeft
659
660 OpDecorate %in_idx Location 0
661 OpDecorate %in_idx Flat
662 OpDecorate %in_addr Location 1
663 OpDecorate %in_addr AliasedPointerEXT
664 OpDecorate %in_addr Flat
665 OpDecorate %dEQP_FragColor Location 0
666
667 OpDecorate %rta ArrayStride 16
668 OpDecorate %vec4_psb ArrayStride 16
669 OpDecorate %srta Block
670 OpMemberDecorate %srta 0 Offset 0
671
672 %void = OpTypeVoid
673 %voidf = OpTypeFunction %void
674
675 %int = OpTypeInt 32 1
676 %flt = OpTypeFloat 32
677 %vec4 = OpTypeVector %flt 4
678 %rta = OpTypeRuntimeArray %vec4
679
680 %zero = OpConstant %int 0
681
682 %int_in = OpTypePointer Input %int
683 %in_idx = OpVariable %int_in Input
684
685 %vec4_out = OpTypePointer Output %vec4
686 %dEQP_FragColor = OpVariable %vec4_out Output
687
688 %srta = OpTypeStruct %rta
689 %srta_psb = OpTypePointer PhysicalStorageBuffer %srta
690 %srta_psb_in = OpTypePointer Input %srta_psb
691 %in_addr = OpVariable %srta_psb_in Input
692 %rta_psb = OpTypePointer PhysicalStorageBuffer %rta
693 %rta_in = OpTypePointer Input %rta
694 %vec4_psb = OpTypePointer PhysicalStorageBuffer %vec4
695
696 %frag = OpFunction %void None %voidf
697 %frag_begin = OpLabel
698
699 %vidx = OpLoad %int %in_idx
700 %vaddr = OpLoad %srta_psb %in_addr
701 %pcolor = OpAccessChain %vec4_psb %vaddr %zero %vidx
702 %color = OpLoad %vec4 %pcolor Aligned 16
703 OpStore %dEQP_FragColor %color
704 OpReturn
705 OpFunctionEnd
706 )");
707
708 programCollection.spirvAsmSources.add("vert")
709 << vert
710 << vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
711 programCollection.spirvAsmSources.add("frag")
712 << frag
713 << vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
714 }
715
prepareColorBuffer(bool flushAfter) const716 ut::TypedBuffer<tcu::Vec4> SpvAsmPhysicalStorageBufferVertexInOutInTestInstance::prepareColorBuffer (bool flushAfter) const
717 {
718 const deUint32 colorCount = 21;
719 tcu::Vec4 colors [colorCount];
720 tcu::Vec4 color (-1.0f, +1.0f, +1.0f, -1.0f);
721
722 for (deUint32 c = 0; c < colorCount; ++c)
723 {
724 colors[c] = color;
725
726 color[0] += 0.1f;
727 color[1] -= 0.1f;
728 color[2] -= 0.1f;
729 color[3] += 0.1f;
730 }
731
732 ut::TypedBuffer<tcu::Vec4> buffer(m_context, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, (m_params->elements * m_params->elements), true);
733 for (auto j = buffer.begin(), begin = j; j != buffer.end(); ++j)
734 {
735 *j = colors[std::distance(begin, j) % colorCount];
736 }
737
738 if (flushAfter) buffer.flush();
739 return buffer;
740 }
741
742 ut::TypedBuffer<SpvAsmPhysicalStorageBufferVertexInOutInTestInstance::Attribute>
prepareVertexAttributes(deUint64 address) const743 SpvAsmPhysicalStorageBufferVertexInOutInTestInstance::prepareVertexAttributes (deUint64 address) const
744 {
745 const float xStep = 2.0f / static_cast<float>(m_params->elements);
746 const float yStep = 2.0f / static_cast<float>(m_params->elements);
747 const float xStart = -1.0f + xStep / 2.0f;
748 const float yStart = -1.0f + yStep / 2.0f;
749
750 float x = xStart;
751 float y = yStart;
752
753 ut::TypedBuffer<Attribute> attrs (m_context, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, (m_params->elements * m_params->elements));
754
755 for (deUint32 row = 0; row < m_params->elements; ++row)
756 {
757 for (deUint32 col = 0; col < m_params->elements; ++col)
758 {
759 Attribute& attr = attrs[(row*m_params->elements)+col];
760 attr.position = tcu::Vec4(x, y, 0.0f, 1.0f);
761 attr.address = address;
762
763 x += xStep;
764 }
765 y += yStep;
766 x = xStart;
767 }
768
769 attrs.flush();
770
771 return attrs;
772 }
773
createGraphicsPipeline(VkPipelineLayout pipelineLayout,VkRenderPass renderPass,VkShaderModule vertexModule,VkShaderModule fragmentModule) const774 Move<VkPipeline> SpvAsmPhysicalStorageBufferVertexInOutInTestInstance::createGraphicsPipeline (VkPipelineLayout pipelineLayout,
775 VkRenderPass renderPass,
776 VkShaderModule vertexModule,
777 VkShaderModule fragmentModule) const
778 {
779 const DeviceInterface& vk = m_context.getDeviceInterface();
780 const VkDevice device = m_context.getDevice();
781 const std::vector<VkRect2D> scissors (1, makeRect2D(m_params->elements, m_params->elements));
782 const std::vector<VkViewport> viewports (1, makeViewport(m_params->elements, m_params->elements));
783
784 const VkVertexInputBindingDescription bindingDescriptions[] =
785 {
786 {
787 0u, // binding
788 sizeof(Attribute), // stride
789 VK_VERTEX_INPUT_RATE_VERTEX, // inputRate
790 },
791 };
792
793 const VkVertexInputAttributeDescription attributeDescriptions[] =
794 {
795 {
796 0u, // location
797 0u, // binding
798 VK_FORMAT_R32G32B32A32_SFLOAT, // format
799 0u // offset
800 },
801 {
802 1u, // location
803 0u, // binding
804 VK_FORMAT_R64_UINT, // format
805 static_cast<deUint32>(sizeof(Attribute::position)) // offset
806 },
807 };
808
809 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
810 {
811 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
812 DE_NULL,
813 (VkPipelineVertexInputStateCreateFlags)0, // flags
814 DE_LENGTH_OF_ARRAY(bindingDescriptions), // vertexBindingDescriptionCount
815 bindingDescriptions, // pVertexBindingDescriptions
816 DE_LENGTH_OF_ARRAY(attributeDescriptions), // vertexAttributeDescriptionCount
817 attributeDescriptions // pVertexAttributeDescriptions
818 };
819
820 return vk::makeGraphicsPipeline(
821 vk, // vk
822 device, // device
823 pipelineLayout, // pipelineLayout
824 vertexModule, // vertexShaderModule
825 DE_NULL, // tessellationControlModule
826 DE_NULL, // tessellationEvalModule
827 DE_NULL, // geometryShaderModule
828 fragmentModule, // fragmentShaderModule
829 renderPass, // renderPass
830 viewports, // viewports
831 scissors, // scissors
832 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // topology
833 0U, // subpass
834 0U, // patchControlPoints
835 &vertexInputStateCreateInfo, // vertexInputStateCreateInfo
836 DE_NULL, // rasterizationStateCreateInfo
837 DE_NULL, // multisampleStateCreateInfo
838 DE_NULL, // depthStencilStateCreateInfo
839 DE_NULL, // colorBlendStateCreateInfo
840 DE_NULL); // dynamicStateCreateInfo
841 }
842
iterate(void)843 tcu::TestStatus SpvAsmPhysicalStorageBufferVertexInOutInTestInstance::iterate (void)
844 {
845 const DeviceInterface& vki = m_context.getDeviceInterface();
846 const VkDevice dev = m_context.getDevice();
847 const VkQueue queue = m_context.getUniversalQueue();
848 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
849 const VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT;
850 const VkRect2D renderArea = makeRect2D(m_params->elements, m_params->elements);
851
852 Move<VkCommandPool> cmdPool = createCommandPool(vki, dev, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
853 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vki, dev, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
854
855 ut::Image image (m_context, m_params->elements, m_params->elements, format);
856 Move<VkRenderPass> renderPass = image.createRenderPass();
857 Move<VkFramebuffer> framebuffer = image.createFramebuffer(*renderPass);
858
859 Move<VkShaderModule> vertexModule = createShaderModule(vki, dev, m_context.getBinaryCollection().get("vert"), 0);
860 Move<VkShaderModule> fragmentModule = createShaderModule(vki, dev, m_context.getBinaryCollection().get("frag"), 0);
861 Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vki, dev, 0u, DE_NULL);
862 Move<VkPipeline> pipeline = createGraphicsPipeline(*pipelineLayout, *renderPass, *vertexModule, *fragmentModule);
863
864 ut::TypedBuffer<tcu::Vec4> colorBuffer = prepareColorBuffer();
865 ut::TypedBuffer<Attribute> attributes = prepareVertexAttributes(colorBuffer.getDeviceAddress());
866 const VkBuffer vertexBuffers[] = { attributes.getBuffer() };
867 const VkDeviceSize vertexOffsets[] = { 0u };
868 const tcu::Vec4 clearColor (-1.0f);
869
870 beginCommandBuffer(vki, *cmdBuffer);
871 vki.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
872 vki.cmdBindVertexBuffers(*cmdBuffer, 0, 1, vertexBuffers, vertexOffsets);
873 beginRenderPass(vki, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
874 vki.cmdDraw(*cmdBuffer, (m_params->elements * m_params->elements), 1u, 0u, 0u);
875 endRenderPass(vki, *cmdBuffer);
876 image.downloadAfterDraw(*cmdBuffer);
877 endCommandBuffer(vki, *cmdBuffer);
878
879 submitCommandsAndWait(vki, dev, queue, *cmdBuffer);
880
881 ut::TypedBuffer<tcu::Vec4> resultBuffer = image.getBuffer<tcu::Vec4>();
882
883 return std::equal(resultBuffer.begin(), resultBuffer.end(), colorBuffer.begin()) ? tcu::TestStatus::pass("") : tcu::TestStatus::fail("");
884 }
885
initPrograms(vk::SourceCollections & programCollection,const TestParamsPtr params)886 void SpvAsmPhysicalStorageBufferPushConstantsTestInstance::initPrograms (vk::SourceCollections& programCollection, const TestParamsPtr params)
887 {
888 DE_UNREF(params);
889
890 const std::string program(R"(
891 OpCapability Shader
892 OpCapability PhysicalStorageBufferAddresses
893
894 OpExtension "SPV_KHR_physical_storage_buffer"
895 OpMemoryModel PhysicalStorageBuffer64 GLSL450
896
897 OpEntryPoint GLCompute %main "main" %id %str
898
899 OpExecutionMode %main LocalSize 1 1 1
900 OpSource GLSL 450
901 OpName %main "main"
902 OpName %id "gl_GlobalInvocationID"
903 OpName %src "source"
904 OpName %dst "destination"
905 OpName %src_buf "source"
906 OpName %dst_buf "destination"
907 OpDecorate %id BuiltIn GlobalInvocationId
908
909 OpDecorate %str_t Block
910 OpMemberDecorate %str_t 0 Offset 0
911 OpMemberDecorate %str_t 1 Offset 8
912 OpMemberDecorate %str_t 2 Offset 16
913 OpMemberDecorate %str_t 3 Offset 20
914
915 OpDecorate %src_buf Restrict
916 OpDecorate %dst_buf Restrict
917
918 OpDecorate %int_arr ArrayStride 4
919
920 %int = OpTypeInt 32 1
921 %int_ptr = OpTypePointer PhysicalStorageBuffer %int
922 %int_fptr = OpTypePointer Function %int
923 %zero = OpConstant %int 0
924 %one = OpConstant %int 1
925 %two = OpConstant %int 2
926 %three = OpConstant %int 3
927
928 %uint = OpTypeInt 32 0
929 %uint_ptr = OpTypePointer Input %uint
930 %uint_fptr = OpTypePointer Function %uint
931 %uvec3 = OpTypeVector %uint 3
932 %uvec3ptr = OpTypePointer Input %uvec3
933 %uzero = OpConstant %uint 0
934 %id = OpVariable %uvec3ptr Input
935
936 %int_arr = OpTypeRuntimeArray %int
937
938 %buf_ptr = OpTypePointer PhysicalStorageBuffer %int_arr
939 %str_t = OpTypeStruct %buf_ptr %buf_ptr %int %int
940 %str_ptr = OpTypePointer PushConstant %str_t
941 %str = OpVariable %str_ptr PushConstant
942 %buf_ptr_fld = OpTypePointer PushConstant %buf_ptr
943 %int_fld = OpTypePointer PushConstant %int
944
945 %bool = OpTypeBool
946 %void = OpTypeVoid
947 %voidf = OpTypeFunction %void
948 %cpbuffsf = OpTypeFunction %void %buf_ptr %buf_ptr %int
949
950 %cpbuffs = OpFunction %void None %cpbuffsf
951 %src_buf = OpFunctionParameter %buf_ptr
952 %dst_buf = OpFunctionParameter %buf_ptr
953 %elements = OpFunctionParameter %int
954 %cp_begin = OpLabel
955 %j = OpVariable %int_fptr Function
956 OpStore %j %zero
957 OpBranch %for
958 %for = OpLabel
959 %vj = OpLoad %int %j
960 %cj = OpULessThan %bool %vj %elements
961 OpLoopMerge %for_end %incj None
962 OpBranchConditional %cj %for_body %for_end
963 %for_body = OpLabel
964 %src_el_lnk = OpAccessChain %int_ptr %src_buf %vj
965 %dst_el_lnk = OpAccessChain %int_ptr %dst_buf %vj
966 %src_el = OpLoad %int %src_el_lnk Aligned 4
967 OpStore %dst_el_lnk %src_el Aligned 4
968 OpBranch %incj
969 %incj = OpLabel
970 %nj = OpIAdd %int %vj %one
971 OpStore %j %nj
972 OpBranch %for
973 %for_end = OpLabel
974 OpReturn
975 OpFunctionEnd
976
977 %main = OpFunction %void None %voidf
978 %begin = OpLabel
979 %i = OpVariable %int_fptr Function
980 OpStore %i %zero
981 %src_lnk = OpAccessChain %buf_ptr_fld %str %zero
982 %dst_lnk = OpAccessChain %buf_ptr_fld %str %one
983 %cnt_lnk = OpAccessChain %int_fld %str %two
984 %use_fun_lnk = OpAccessChain %int_fld %str %three
985 %src = OpLoad %buf_ptr %src_lnk
986 %dst = OpLoad %buf_ptr %dst_lnk
987 %cnt = OpLoad %int %cnt_lnk
988 %use_fun = OpLoad %int %use_fun_lnk
989
990 %cuf = OpINotEqual %bool %use_fun %zero
991 OpSelectionMerge %use_fun_end None
992 OpBranchConditional %cuf %copy %loop
993 %copy = OpLabel
994 %unused = OpFunctionCall %void %cpbuffs %src %dst %cnt
995 OpBranch %use_fun_end
996 %loop = OpLabel
997 %vi = OpLoad %int %i
998 %ci = OpSLessThan %bool %vi %cnt
999 OpLoopMerge %loop_end %inci None
1000 OpBranchConditional %ci %loop_body %loop_end
1001 %loop_body = OpLabel
1002 %src_px_lnk = OpAccessChain %int_ptr %src %vi
1003 %dst_px_lnk = OpAccessChain %int_ptr %dst %vi
1004 %src_px = OpLoad %int %src_px_lnk Aligned 4
1005 OpStore %dst_px_lnk %src_px Aligned 4
1006 OpBranch %inci
1007 %inci = OpLabel
1008 %ni = OpIAdd %int %vi %one
1009 OpStore %i %ni
1010 OpBranch %loop
1011 %loop_end = OpLabel
1012 OpBranch %use_fun_end
1013 %use_fun_end = OpLabel
1014
1015 OpReturn
1016 OpFunctionEnd
1017 )");
1018
1019 programCollection.spirvAsmSources.add("comp")
1020 << program
1021 << vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
1022 }
1023
iterate(void)1024 tcu::TestStatus SpvAsmPhysicalStorageBufferPushConstantsTestInstance::iterate (void)
1025 {
1026 const DeviceInterface& vki = m_context.getDeviceInterface();
1027 const VkDevice dev = m_context.getDevice();
1028 const VkQueue queue = m_context.getUniversalQueue();
1029 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1030
1031 Move<VkCommandPool> cmdPool = createCommandPool(vki, dev, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1032 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vki, dev, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1033 Move<VkShaderModule> shaderModule = createShaderModule(vki, dev, m_context.getBinaryCollection().get("comp"), 0);
1034
1035 struct PushConstant
1036 {
1037 deUint64 src;
1038 deUint64 dst;
1039 deInt32 cnt;
1040 deBool use_fun;
1041 };
1042
1043 VkPushConstantRange pushConstantRange =
1044 {
1045 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
1046 0, // deUint32 offset;
1047 sizeof(PushConstant) // deUint32 size;
1048 };
1049
1050 Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vki, dev, 0, DE_NULL, 1, &pushConstantRange);
1051 Move<VkPipeline> pipeline = makeComputePipeline(vki, dev, *pipelineLayout, 0, *shaderModule, 0, DE_NULL);
1052
1053 ut::TypedBuffer<deInt32> src (m_context, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, m_params->elements, true);
1054 ut::TypedBuffer<deInt32> dst (m_context, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, m_params->elements, true);
1055
1056 src.iota(m_params->elements, true);
1057 dst.zero(true);
1058
1059 const PushConstant pc = { src.getDeviceAddress(), dst.getDeviceAddress(), deInt32(m_params->elements), (m_params->method == PassMethod::PUSH_CONSTANTS_FUNCTION ? 1 : 0) };
1060
1061 beginCommandBuffer(vki, *cmdBuffer);
1062 vki.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1063 vki.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(pc), &pc);
1064 vki.cmdDispatch(*cmdBuffer, 1, 1, 1);
1065 endCommandBuffer(vki, *cmdBuffer);
1066
1067 submitCommandsAndWait(vki, dev, queue, *cmdBuffer);
1068
1069 dst.invalidate();
1070
1071 return std::equal(src.begin(), src.end(), dst.begin()) ? tcu::TestStatus::pass("") : tcu::TestStatus::fail("");
1072 }
1073
initPrograms(vk::SourceCollections & programCollection,const TestParamsPtr params)1074 void SpvAsmPhysicalStorageBufferAddrsInSSBOTestInstance::initPrograms (vk::SourceCollections& programCollection, const TestParamsPtr params)
1075 {
1076 DE_UNREF(params);
1077
1078 const std::string comp(R"(
1079 OpCapability Shader
1080 OpCapability Int64
1081 OpCapability PhysicalStorageBufferAddresses
1082
1083 OpExtension "SPV_KHR_physical_storage_buffer"
1084 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1085
1086 OpEntryPoint GLCompute %comp "main" %id %ssbo
1087
1088 OpExecutionMode %comp LocalSize 1 1 1
1089 OpDecorate %id BuiltIn GlobalInvocationId
1090
1091 OpDecorate %sssbo Block
1092 OpMemberDecorate %sssbo 0 Offset 0
1093 OpMemberDecorate %sssbo 1 Offset 8
1094 OpMemberDecorate %sssbo 2 Offset 16
1095 OpMemberDecorate %sssbo 3 Offset 24
1096
1097 OpDecorate %ssbo DescriptorSet 0
1098 OpDecorate %ssbo Binding 0
1099
1100 OpDecorate %rta ArrayStride 4
1101
1102 %bool = OpTypeBool
1103 %int = OpTypeInt 32 1
1104 %uint = OpTypeInt 32 0
1105 %ulong = OpTypeInt 64 0
1106
1107 %zero = OpConstant %int 0
1108 %one = OpConstant %int 1
1109 %two = OpConstant %int 2
1110 %three = OpConstant %int 3
1111
1112 %uvec3 = OpTypeVector %uint 3
1113 %rta = OpTypeRuntimeArray %int
1114
1115 %rta_psb = OpTypePointer PhysicalStorageBuffer %rta
1116 %sssbo = OpTypeStruct %rta_psb %ulong %rta_psb %ulong
1117 %sssbo_buf = OpTypePointer StorageBuffer %sssbo
1118 %ssbo = OpVariable %sssbo_buf StorageBuffer
1119 %rta_psb_sb = OpTypePointer StorageBuffer %rta_psb
1120 %int_psb = OpTypePointer PhysicalStorageBuffer %int
1121 %ulong_sb = OpTypePointer StorageBuffer %ulong
1122
1123 %uvec3_in = OpTypePointer Input %uvec3
1124 %id = OpVariable %uvec3_in Input
1125 %uint_in = OpTypePointer Input %uint
1126
1127 %void = OpTypeVoid
1128 %voidf = OpTypeFunction %void
1129
1130 %comp = OpFunction %void None %voidf
1131 %comp_begin = OpLabel
1132
1133 %pgid_x = OpAccessChain %uint_in %id %zero
1134 %gid_x = OpLoad %uint %pgid_x
1135 %mod2 = OpSMod %int %gid_x %two
1136 %even = OpIEqual %bool %mod2 %zero
1137
1138 %psrc_buff_p = OpAccessChain %rta_psb_sb %ssbo %zero
1139 %pdst_buff_p = OpAccessChain %rta_psb_sb %ssbo %two
1140 %src_buff_p = OpLoad %rta_psb %psrc_buff_p
1141 %dst_buff_p = OpLoad %rta_psb %pdst_buff_p
1142
1143 %psrc_buff_u = OpAccessChain %ulong_sb %ssbo %one
1144 %psrc_buff_v = OpLoad %ulong %psrc_buff_u
1145 %src_buff_v = OpConvertUToPtr %rta_psb %psrc_buff_v
1146 %pdst_buff_u = OpAccessChain %ulong_sb %ssbo %three
1147 %pdst_buff_v = OpLoad %ulong %pdst_buff_u
1148 %dst_buff_v = OpConvertUToPtr %rta_psb %pdst_buff_v
1149
1150 %src = OpSelect %rta_psb %even %src_buff_p %src_buff_v
1151 %dst = OpSelect %rta_psb %even %dst_buff_v %dst_buff_p
1152
1153 %psrc_color = OpAccessChain %int_psb %src %gid_x
1154 %src_color = OpLoad %int %psrc_color Aligned 4
1155 %pdst_color = OpAccessChain %int_psb %dst %gid_x
1156 OpStore %pdst_color %src_color Aligned 4
1157
1158 OpReturn
1159 OpFunctionEnd
1160 )");
1161
1162 programCollection.spirvAsmSources.add("comp")
1163 << comp
1164 << vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
1165 }
1166
1167 /*
1168 Below test does not add anything new. The main purpose of this test is to show that both PhysicalStorageBuffer
1169 and 64-bit integer value can coexist in one array one next to the other. In the both cases, when the one address
1170 has its own dedicated storage class and the other is regular integer, the shader is responsible for how to interpret
1171 and use input addresses. Regardless of the shader, the application always passes them as 64-bit integers.
1172 */
iterate(void)1173 tcu::TestStatus SpvAsmPhysicalStorageBufferAddrsInSSBOTestInstance::iterate (void)
1174 {
1175 const DeviceInterface& vki = m_context.getDeviceInterface();
1176 const VkDevice dev = m_context.getDevice();
1177 const VkQueue queue = m_context.getUniversalQueue();
1178 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1179
1180 Move<VkCommandPool> cmdPool = createCommandPool(vki, dev, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1181 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vki, dev, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1182 Move<VkShaderModule> shaderModule = createShaderModule(vki, dev, m_context.getBinaryCollection().get("comp"), 0);
1183
1184 Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
1185 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1186 .build(vki, dev);
1187 Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
1188 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1189 .build(vki, dev, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1190 Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vki, dev, *descriptorPool, *descriptorSetLayout);
1191 Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vki, dev, 1u, &descriptorSetLayout.get());
1192 Move<VkPipeline> pipeline = makeComputePipeline(vki, dev, *pipelineLayout, 0, *shaderModule, 0, DE_NULL);
1193
1194
1195 ut::TypedBuffer<deInt32> src (m_context, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, m_params->elements, true);
1196 ut::TypedBuffer<deInt32> dst (m_context, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, m_params->elements, true);
1197
1198 struct SSBO
1199 {
1200 deUint64 srcAsBuff;
1201 deUint64 srcAsUint;
1202 deUint64 dstAsBuff;
1203 deUint64 dstAsUint;
1204 };
1205 ut::TypedBuffer<SSBO> ssbo (m_context, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, {
1206 {
1207 src.getDeviceAddress(),
1208 src.getDeviceAddress(),
1209 dst.getDeviceAddress(),
1210 dst.getDeviceAddress()
1211 }
1212 });
1213 VkDescriptorBufferInfo ssboBufferInfo = makeDescriptorBufferInfo(ssbo.getBuffer(), 0, ssbo.getSize());
1214 DescriptorSetUpdateBuilder () .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboBufferInfo)
1215 .update(vki, dev);
1216
1217 src.iota(m_params->elements, true);
1218 dst.zero(true);
1219
1220 beginCommandBuffer(vki, *cmdBuffer);
1221 vki.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1222 vki.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1223 vki.cmdDispatch(*cmdBuffer, m_params->elements, 1, 1);
1224 endCommandBuffer(vki, *cmdBuffer);
1225
1226 submitCommandsAndWait(vki, dev, queue, *cmdBuffer);
1227
1228 dst.invalidate();
1229
1230 return std::equal(src.begin(), src.end(), dst.begin()) ? tcu::TestStatus::pass("") : tcu::TestStatus::fail("");
1231 }
1232
1233 } // unnamed
1234
createPhysicalStorageBufferTestGroup(tcu::TestContext & testCtx)1235 tcu::TestCaseGroup* createPhysicalStorageBufferTestGroup (tcu::TestContext& testCtx)
1236 {
1237 struct
1238 {
1239 PassMethod method;
1240 std::string testName;
1241 }
1242 const methods[] =
1243 {
1244 { PassMethod::PUSH_CONSTANTS, "push_constants" },
1245 { PassMethod::PUSH_CONSTANTS_FUNCTION, "push_constants_function" },
1246 { PassMethod::VERTEX_IN_OUT_IN, "vertex_in_out_in" },
1247 { PassMethod::ADDRESSES_IN_SSBO, "addrs_in_ssbo" },
1248 };
1249
1250 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(testCtx, "physical_storage_buffer", "Various methods of PhysicalStorageBuffer passing");
1251
1252 for (const auto& method : methods)
1253 {
1254 group->addChild(new SpvAsmPhysicalStorageBufferTestCase(testCtx, method.testName, TestParamsPtr(new TestParams({method.method, 64}))));
1255 }
1256
1257 return group;
1258 }
1259
1260 } // SpirVAssembly
1261 } // vkt
1262
1263