1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2020 The Khronos Group 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 Testing acceleration structures in ray query extension
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktRayQueryAccelerationStructuresTests.hpp"
25
26 #include <array>
27 #include <set>
28 #include <limits>
29
30 #include "vkDefs.hpp"
31 #include "deClock.h"
32 #include "vktTestCase.hpp"
33 #include "vktTestGroupUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkBarrierUtil.hpp"
38 #include "vkBufferWithMemory.hpp"
39 #include "vkImageWithMemory.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkImageUtil.hpp"
42 #include "vkRayTracingUtil.hpp"
43 #include "deRandom.hpp"
44 #include "tcuTexture.hpp"
45 #include "tcuTextureUtil.hpp"
46 #include "tcuTestLog.hpp"
47 #include "tcuImageCompare.hpp"
48 #include "tcuFloat.hpp"
49 #include "deModularCounter.hpp"
50
51 namespace vkt
52 {
53 namespace RayQuery
54 {
55 namespace
56 {
57 using namespace vk;
58 using namespace vkt;
59
60 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
61 VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR |
62 VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
63
64 enum ShaderSourcePipeline
65 {
66 SSP_GRAPHICS_PIPELINE,
67 SSP_COMPUTE_PIPELINE,
68 SSP_RAY_TRACING_PIPELINE
69 };
70
71 enum ShaderSourceType
72 {
73 SST_VERTEX_SHADER,
74 SST_TESSELATION_CONTROL_SHADER,
75 SST_TESSELATION_EVALUATION_SHADER,
76 SST_GEOMETRY_SHADER,
77 SST_FRAGMENT_SHADER,
78 SST_COMPUTE_SHADER,
79 SST_RAY_GENERATION_SHADER,
80 SST_INTERSECTION_SHADER,
81 SST_ANY_HIT_SHADER,
82 SST_CLOSEST_HIT_SHADER,
83 SST_MISS_SHADER,
84 SST_CALLABLE_SHADER,
85 };
86
87 enum ShaderTestType
88 {
89 STT_GENERATE_INTERSECTION = 0,
90 STT_SKIP_INTERSECTION = 1,
91 };
92
93 enum class BottomTestType
94 {
95 TRIANGLES = 0,
96 AABBS = 1,
97 };
98
99 enum class TopTestType
100 {
101 IDENTICAL_INSTANCES,
102 DIFFERENT_INSTANCES,
103 UPDATED_INSTANCES
104 };
105
106 enum OperationTarget
107 {
108 OT_NONE,
109 OT_TOP_ACCELERATION,
110 OT_BOTTOM_ACCELERATION
111 };
112
113 enum OperationType
114 {
115 OP_NONE,
116 OP_COPY,
117 OP_COMPACT,
118 OP_SERIALIZE,
119 OP_UPDATE,
120 OP_UPDATE_IN_PLACE
121 };
122
123 enum class InstanceCullFlags
124 {
125 NONE,
126 CULL_DISABLE,
127 COUNTERCLOCKWISE,
128 ALL,
129 };
130
131 enum class EmptyAccelerationStructureCase
132 {
133 NOT_EMPTY = 0,
134 INACTIVE_TRIANGLES = 1,
135 INACTIVE_INSTANCES = 2,
136 NO_GEOMETRIES_BOTTOM = 3, // geometryCount zero when building.
137 NO_PRIMITIVES_BOTTOM = 4, // primitiveCount zero when building.
138 NO_PRIMITIVES_TOP = 5, // primitiveCount zero when building.
139 };
140
141 const uint32_t TEST_WIDTH = 8;
142 const uint32_t TEST_HEIGHT = 8;
143
144 struct TestParams;
145
146 class TestConfiguration
147 {
148 public:
149 virtual ~TestConfiguration();
150 virtual void initConfiguration(Context &context, TestParams &testParams) = 0;
151 virtual void fillCommandBuffer(
152 Context &context, TestParams &testParams, VkCommandBuffer commandBuffer,
153 const VkWriteDescriptorSetAccelerationStructureKHR &rayQueryAccelerationStructureWriteDescriptorSet,
154 const VkDescriptorImageInfo &resultImageInfo) = 0;
155 virtual bool verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams) = 0;
156 virtual VkFormat getResultImageFormat() = 0;
157 virtual size_t getResultImageFormatSize() = 0;
158 virtual VkClearValue getClearValue() = 0;
159 };
160
~TestConfiguration()161 TestConfiguration::~TestConfiguration()
162 {
163 }
164
165 class SceneBuilder
166 {
167 public:
~SceneBuilder()168 virtual ~SceneBuilder()
169 {
170 }
171
172 virtual std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
173 Context &context, TestParams &testParams) = 0;
174 virtual de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
175 Context &context, TestParams &testParams,
176 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) = 0;
177 };
178
179 struct TestParams
180 {
181 ShaderSourceType shaderSourceType;
182 ShaderSourcePipeline shaderSourcePipeline;
183 vk::VkAccelerationStructureBuildTypeKHR buildType; // are we making AS on CPU or GPU
184 VkFormat vertexFormat;
185 bool padVertices;
186 VkIndexType indexType;
187 BottomTestType bottomTestType; // what kind of geometry is stored in bottom AS
188 InstanceCullFlags cullFlags; // Flags for instances, if needed.
189 bool bottomUsesAOP; // does bottom AS use arrays, or arrays of pointers
190 bool bottomGeneric; // Bottom created as generic AS type.
191 bool bottomUnboundedCreation; // Bottom created with unbounded buffer memory.
192 TopTestType topTestType; // If instances are identical then bottom geometries must have different vertices/aabbs
193 bool topUsesAOP; // does top AS use arrays, or arrays of pointers
194 bool topGeneric; // Top created as generic AS type.
195 bool topUnboundedCreation; // Top created with unbounded buffer memory.
196 VkBuildAccelerationStructureFlagsKHR buildFlags;
197 OperationTarget operationTarget;
198 OperationType operationType;
199 uint32_t width;
200 uint32_t height;
201 uint32_t workerThreadsCount;
202 EmptyAccelerationStructureCase emptyASCase;
203 };
204
getShaderGroupHandleSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)205 uint32_t getShaderGroupHandleSize(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
206 {
207 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
208
209 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
210 return rayTracingPropertiesKHR->getShaderGroupHandleSize();
211 }
212
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)213 uint32_t getShaderGroupBaseAlignment(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
214 {
215 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
216
217 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
218 return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
219 }
220
makeImageCreateInfo(uint32_t width,uint32_t height,uint32_t depth,VkFormat format)221 VkImageCreateInfo makeImageCreateInfo(uint32_t width, uint32_t height, uint32_t depth, VkFormat format)
222 {
223 const VkImageCreateInfo imageCreateInfo = {
224 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
225 DE_NULL, // const void* pNext;
226 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
227 VK_IMAGE_TYPE_3D, // VkImageType imageType;
228 format, // VkFormat format;
229 makeExtent3D(width, height, depth), // VkExtent3D extent;
230 1u, // uint32_t mipLevels;
231 1u, // uint32_t arrayLayers;
232 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
233 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
234 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
235 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
236 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
237 0u, // uint32_t queueFamilyIndexCount;
238 DE_NULL, // const uint32_t* pQueueFamilyIndices;
239 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
240 };
241
242 return imageCreateInfo;
243 }
244
makeQueryPool(const DeviceInterface & vk,const VkDevice device,const VkQueryType queryType,uint32_t queryCount)245 Move<VkQueryPool> makeQueryPool(const DeviceInterface &vk, const VkDevice device, const VkQueryType queryType,
246 uint32_t queryCount)
247 {
248 const VkQueryPoolCreateInfo queryPoolCreateInfo = {
249 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
250 DE_NULL, // pNext
251 (VkQueryPoolCreateFlags)0, // flags
252 queryType, // queryType
253 queryCount, // queryCount
254 0u, // pipelineStatistics
255 };
256 return createQueryPool(vk, device, &queryPoolCreateInfo);
257 }
258
registerShaderModule(const DeviceInterface & vkd,const VkDevice device,Context & context,std::vector<de::SharedPtr<Move<VkShaderModule>>> & shaderModules,std::vector<VkPipelineShaderStageCreateInfo> & shaderCreateInfos,VkShaderStageFlagBits stage,const std::string & externalNamePart,const std::string & internalNamePart)259 bool registerShaderModule(const DeviceInterface &vkd, const VkDevice device, Context &context,
260 std::vector<de::SharedPtr<Move<VkShaderModule>>> &shaderModules,
261 std::vector<VkPipelineShaderStageCreateInfo> &shaderCreateInfos, VkShaderStageFlagBits stage,
262 const std::string &externalNamePart, const std::string &internalNamePart)
263 {
264 char fullShaderName[40];
265 snprintf(fullShaderName, 40, externalNamePart.c_str(), internalNamePart.c_str());
266 std::string fsn = fullShaderName;
267 if (fsn.empty())
268 return false;
269
270 shaderModules.push_back(
271 makeVkSharedPtr(createShaderModule(vkd, device, context.getBinaryCollection().get(fsn), 0)));
272
273 shaderCreateInfos.push_back({
274 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, DE_NULL, (VkPipelineShaderStageCreateFlags)0,
275 stage, // stage
276 shaderModules.back()->get(), // shader
277 "main",
278 DE_NULL, // pSpecializationInfo
279 });
280
281 return true;
282 }
283
registerShaderModule(const DeviceInterface & vkd,const VkDevice device,Context & context,RayTracingPipeline & rayTracingPipeline,VkShaderStageFlagBits shaderStage,const std::string & externalNamePart,const std::string & internalNamePart,uint32_t groupIndex)284 bool registerShaderModule(const DeviceInterface &vkd, const VkDevice device, Context &context,
285 RayTracingPipeline &rayTracingPipeline, VkShaderStageFlagBits shaderStage,
286 const std::string &externalNamePart, const std::string &internalNamePart, uint32_t groupIndex)
287 {
288 char fullShaderName[40];
289 snprintf(fullShaderName, 40, externalNamePart.c_str(), internalNamePart.c_str());
290 std::string fsn = fullShaderName;
291 if (fsn.empty())
292 return false;
293 Move<VkShaderModule> shaderModule = createShaderModule(vkd, device, context.getBinaryCollection().get(fsn), 0);
294 if (*shaderModule == DE_NULL)
295 return false;
296 rayTracingPipeline.addShader(shaderStage, shaderModule, groupIndex);
297 return true;
298 }
299
getCullFlags(InstanceCullFlags flags)300 VkGeometryInstanceFlagsKHR getCullFlags(InstanceCullFlags flags)
301 {
302 VkGeometryInstanceFlagsKHR cullFlags = 0u;
303
304 if (flags == InstanceCullFlags::CULL_DISABLE || flags == InstanceCullFlags::ALL)
305 cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
306
307 if (flags == InstanceCullFlags::COUNTERCLOCKWISE || flags == InstanceCullFlags::ALL)
308 cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR;
309
310 return cullFlags;
311 }
312
313 class GraphicsConfiguration : public TestConfiguration
314 {
315 public:
316 virtual ~GraphicsConfiguration();
317 void initConfiguration(Context &context, TestParams &testParams) override;
318 void fillCommandBuffer(
319 Context &context, TestParams &testParams, VkCommandBuffer commandBuffer,
320 const VkWriteDescriptorSetAccelerationStructureKHR &rayQueryAccelerationStructureWriteDescriptorSet,
321 const VkDescriptorImageInfo &resultImageInfo) override;
322 bool verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams) override;
323 VkFormat getResultImageFormat() override;
324 size_t getResultImageFormatSize() override;
325 VkClearValue getClearValue() override;
326
327 protected:
328 Move<VkDescriptorSetLayout> descriptorSetLayout;
329 Move<VkDescriptorPool> descriptorPool;
330 Move<VkDescriptorSet> descriptorSet;
331 Move<VkPipelineLayout> pipelineLayout;
332 Move<VkRenderPass> renderPass;
333 Move<VkFramebuffer> framebuffer;
334 std::vector<de::SharedPtr<Move<VkShaderModule>>> shaderModules;
335 Move<VkPipeline> pipeline;
336 std::vector<tcu::Vec3> vertices;
337 Move<VkBuffer> vertexBuffer;
338 de::MovePtr<Allocation> vertexAlloc;
339 };
340
~GraphicsConfiguration()341 GraphicsConfiguration::~GraphicsConfiguration()
342 {
343 shaderModules.clear();
344 }
345
initConfiguration(Context & context,TestParams & testParams)346 void GraphicsConfiguration::initConfiguration(Context &context, TestParams &testParams)
347 {
348 const DeviceInterface &vkd = context.getDeviceInterface();
349 const VkDevice device = context.getDevice();
350 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
351 Allocator &allocator = context.getDefaultAllocator();
352
353 descriptorSetLayout =
354 DescriptorSetLayoutBuilder()
355 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_ALL_GRAPHICS)
356 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_ALL_GRAPHICS)
357 .build(vkd, device);
358 descriptorPool = DescriptorPoolBuilder()
359 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
360 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
361 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
362 descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
363 pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
364
365 std::vector<std::string> rayQueryTestName;
366 rayQueryTestName.push_back("as_triangle");
367 rayQueryTestName.push_back("as_aabb");
368
369 const std::map<ShaderSourceType, std::vector<std::string>> shaderNames = {
370 //idx: 0 1 2 3 4
371 //shader: vert, tesc, tese, geom, frag,
372 {SST_VERTEX_SHADER,
373 {
374 "vert_%s",
375 "",
376 "",
377 "",
378 "",
379 }},
380 {SST_TESSELATION_CONTROL_SHADER,
381 {
382 "vert",
383 "tesc_%s",
384 "tese",
385 "",
386 "",
387 }},
388 {SST_TESSELATION_EVALUATION_SHADER,
389 {
390 "vert",
391 "tesc",
392 "tese_%s",
393 "",
394 "",
395 }},
396 {SST_GEOMETRY_SHADER,
397 {
398 "vert_vid",
399 "",
400 "",
401 "geom_%s",
402 "",
403 }},
404 {SST_FRAGMENT_SHADER,
405 {
406 "vert",
407 "",
408 "",
409 "",
410 "frag_%s",
411 }},
412 };
413
414 auto shaderNameIt = shaderNames.find(testParams.shaderSourceType);
415 if (shaderNameIt == end(shaderNames))
416 TCU_THROW(InternalError, "Wrong shader source type");
417
418 std::vector<VkPipelineShaderStageCreateInfo> shaderCreateInfos;
419 bool tescX, teseX, fragX;
420 const auto bottomTestTypeIdx = static_cast<int>(testParams.bottomTestType);
421 registerShaderModule(vkd, device, context, shaderModules, shaderCreateInfos, VK_SHADER_STAGE_VERTEX_BIT,
422 shaderNameIt->second[0], rayQueryTestName[bottomTestTypeIdx]);
423 tescX = registerShaderModule(vkd, device, context, shaderModules, shaderCreateInfos,
424 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, shaderNameIt->second[1],
425 rayQueryTestName[bottomTestTypeIdx]);
426 teseX = registerShaderModule(vkd, device, context, shaderModules, shaderCreateInfos,
427 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, shaderNameIt->second[2],
428 rayQueryTestName[bottomTestTypeIdx]);
429 registerShaderModule(vkd, device, context, shaderModules, shaderCreateInfos, VK_SHADER_STAGE_GEOMETRY_BIT,
430 shaderNameIt->second[3], rayQueryTestName[bottomTestTypeIdx]);
431 fragX = registerShaderModule(vkd, device, context, shaderModules, shaderCreateInfos, VK_SHADER_STAGE_FRAGMENT_BIT,
432 shaderNameIt->second[4], rayQueryTestName[bottomTestTypeIdx]);
433
434 const vk::VkSubpassDescription subpassDesc = {
435 (vk::VkSubpassDescriptionFlags)0,
436 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
437 0u, // inputCount
438 DE_NULL, // pInputAttachments
439 0u, // colorCount
440 DE_NULL, // pColorAttachments
441 DE_NULL, // pResolveAttachments
442 DE_NULL, // depthStencilAttachment
443 0u, // preserveCount
444 DE_NULL, // pPreserveAttachments
445 };
446 const vk::VkRenderPassCreateInfo renderPassParams = {
447 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType
448 DE_NULL, // pNext
449 (vk::VkRenderPassCreateFlags)0,
450 0u, // attachmentCount
451 DE_NULL, // pAttachments
452 1u, // subpassCount
453 &subpassDesc, // pSubpasses
454 0u, // dependencyCount
455 DE_NULL, // pDependencies
456 };
457
458 renderPass = createRenderPass(vkd, device, &renderPassParams);
459
460 const vk::VkFramebufferCreateInfo framebufferParams = {
461 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType
462 DE_NULL, // pNext
463 (vk::VkFramebufferCreateFlags)0,
464 *renderPass, // renderPass
465 0u, // attachmentCount
466 DE_NULL, // pAttachments
467 testParams.width, // width
468 testParams.height, // height
469 1u, // layers
470 };
471
472 framebuffer = createFramebuffer(vkd, device, &framebufferParams);
473
474 VkPrimitiveTopology testTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
475 tcu::Vec3 v0(0.0f, 0.0f, 0.0f);
476 tcu::Vec3 v1(float(testParams.width) - 1.0f, 0.0f, 0.0f);
477 tcu::Vec3 v2(0.0f, float(testParams.height) - 1.0f, 0.0f);
478 tcu::Vec3 v3(float(testParams.width) - 1.0f, float(testParams.height) - 1.0f, 0.0f);
479
480 switch (testParams.shaderSourceType)
481 {
482 case SST_TESSELATION_CONTROL_SHADER:
483 case SST_TESSELATION_EVALUATION_SHADER:
484 testTopology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
485 vertices.push_back(v0);
486 vertices.push_back(v1);
487 vertices.push_back(v2);
488 vertices.push_back(v1);
489 vertices.push_back(v3);
490 vertices.push_back(v2);
491 break;
492 case SST_VERTEX_SHADER:
493 case SST_GEOMETRY_SHADER:
494 vertices.push_back(v0);
495 vertices.push_back(v1);
496 vertices.push_back(v2);
497 vertices.push_back(v3);
498 break;
499 case SST_FRAGMENT_SHADER:
500 vertices.push_back(tcu::Vec3(-1.0f, 1.0f, 0.0f));
501 vertices.push_back(tcu::Vec3(-1.0f, -1.0f, 0.0f));
502 vertices.push_back(tcu::Vec3(1.0f, 1.0f, 0.0f));
503 vertices.push_back(tcu::Vec3(1.0f, -1.0f, 0.0f));
504 break;
505 default:
506 TCU_THROW(InternalError, "Wrong shader source type");
507 }
508
509 const VkVertexInputBindingDescription vertexInputBindingDescription = {
510 0u, // uint32_t binding;
511 sizeof(tcu::Vec3), // uint32_t stride;
512 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
513 };
514
515 const VkVertexInputAttributeDescription vertexInputAttributeDescription = {
516 0u, // uint32_t location;
517 0u, // uint32_t binding;
518 VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format;
519 0u, // uint32_t offset;
520 };
521
522 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
523 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
524 DE_NULL, // const void* pNext;
525 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
526 1u, // uint32_t vertexBindingDescriptionCount;
527 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
528 1u, // uint32_t vertexAttributeDescriptionCount;
529 &vertexInputAttributeDescription // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
530 };
531
532 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
533 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
534 DE_NULL, // const void* pNext;
535 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
536 testTopology, // VkPrimitiveTopology topology;
537 VK_FALSE // VkBool32 primitiveRestartEnable;
538 };
539
540 const VkPipelineTessellationStateCreateInfo tessellationStateCreateInfo = {
541 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
542 DE_NULL, // const void* pNext;
543 VkPipelineTessellationStateCreateFlags(0u), // VkPipelineTessellationStateCreateFlags flags;
544 3u // uint32_t patchControlPoints;
545 };
546
547 VkViewport viewport = makeViewport(testParams.width, testParams.height);
548 VkRect2D scissor = makeRect2D(testParams.width, testParams.height);
549
550 const VkPipelineViewportStateCreateInfo viewportStateCreateInfo = {
551 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType
552 DE_NULL, // const void* pNext
553 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags
554 1u, // uint32_t viewportCount
555 &viewport, // const VkViewport* pViewports
556 1u, // uint32_t scissorCount
557 &scissor // const VkRect2D* pScissors
558 };
559
560 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
561 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
562 DE_NULL, // const void* pNext;
563 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
564 VK_FALSE, // VkBool32 depthClampEnable;
565 fragX ? VK_FALSE : VK_TRUE, // VkBool32 rasterizerDiscardEnable;
566 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
567 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
568 VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace;
569 VK_FALSE, // VkBool32 depthBiasEnable;
570 0.0f, // float depthBiasConstantFactor;
571 0.0f, // float depthBiasClamp;
572 0.0f, // float depthBiasSlopeFactor;
573 1.0f // float lineWidth;
574 };
575
576 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
577 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
578 DE_NULL, // const void* pNext;
579 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
580 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
581 VK_FALSE, // VkBool32 sampleShadingEnable;
582 0.0f, // float minSampleShading;
583 DE_NULL, // const VkSampleMask* pSampleMask;
584 VK_FALSE, // VkBool32 alphaToCoverageEnable;
585 VK_FALSE // VkBool32 alphaToOneEnable;
586 };
587
588 const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
589 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
590 DE_NULL, // const void* pNext;
591 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
592 false, // VkBool32 logicOpEnable;
593 VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp;
594 0, // uint32_t attachmentCount;
595 DE_NULL, // const VkPipelineColorBlendAttachmentState* pAttachments;
596 {1.0f, 1.0f, 1.0f, 1.0f} // float blendConstants[4];
597 };
598
599 const VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo = {
600 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
601 DE_NULL, // const void* pNext;
602 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
603 static_cast<uint32_t>(shaderCreateInfos.size()), // uint32_t stageCount;
604 shaderCreateInfos.data(), // const VkPipelineShaderStageCreateInfo* pStages;
605 &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
606 &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
607 (tescX || teseX) ? &tessellationStateCreateInfo :
608 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
609 fragX ? &viewportStateCreateInfo : DE_NULL, // const VkPipelineViewportStateCreateInfo* pViewportState;
610 &rasterizationStateCreateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
611 fragX ? &multisampleStateCreateInfo : DE_NULL, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
612 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
613 fragX ? &colorBlendStateCreateInfo : DE_NULL, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
614 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
615 pipelineLayout.get(), // VkPipelineLayout layout;
616 renderPass.get(), // VkRenderPass renderPass;
617 0u, // uint32_t subpass;
618 DE_NULL, // VkPipeline basePipelineHandle;
619 0 // int basePipelineIndex;
620 };
621
622 pipeline = createGraphicsPipeline(vkd, device, DE_NULL, &graphicsPipelineCreateInfo);
623
624 const VkBufferCreateInfo vertexBufferParams = {
625 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
626 DE_NULL, // const void* pNext;
627 0u, // VkBufferCreateFlags flags;
628 VkDeviceSize(sizeof(tcu::Vec3) * vertices.size()), // VkDeviceSize size;
629 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
630 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
631 1u, // uint32_t queueFamilyIndexCount;
632 &queueFamilyIndex // const uint32_t* pQueueFamilyIndices;
633 };
634
635 vertexBuffer = createBuffer(vkd, device, &vertexBufferParams);
636 vertexAlloc =
637 allocator.allocate(getBufferMemoryRequirements(vkd, device, *vertexBuffer), MemoryRequirement::HostVisible);
638 VK_CHECK(vkd.bindBufferMemory(device, *vertexBuffer, vertexAlloc->getMemory(), vertexAlloc->getOffset()));
639
640 // Upload vertex data
641 deMemcpy(vertexAlloc->getHostPtr(), vertices.data(), vertices.size() * sizeof(tcu::Vec3));
642 flushAlloc(vkd, device, *vertexAlloc);
643 }
644
fillCommandBuffer(Context & context,TestParams & testParams,VkCommandBuffer commandBuffer,const VkWriteDescriptorSetAccelerationStructureKHR & rayQueryAccelerationStructureWriteDescriptorSet,const VkDescriptorImageInfo & resultImageInfo)645 void GraphicsConfiguration::fillCommandBuffer(
646 Context &context, TestParams &testParams, VkCommandBuffer commandBuffer,
647 const VkWriteDescriptorSetAccelerationStructureKHR &rayQueryAccelerationStructureWriteDescriptorSet,
648 const VkDescriptorImageInfo &resultImageInfo)
649 {
650 const DeviceInterface &vkd = context.getDeviceInterface();
651 const VkDevice device = context.getDevice();
652
653 DescriptorSetUpdateBuilder()
654 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
655 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo)
656 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
657 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet)
658 .update(vkd, device);
659
660 const VkRenderPassBeginInfo renderPassBeginInfo = {
661 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
662 DE_NULL, // const void* pNext;
663 *renderPass, // VkRenderPass renderPass;
664 *framebuffer, // VkFramebuffer framebuffer;
665 makeRect2D(testParams.width, testParams.height), // VkRect2D renderArea;
666 0u, // uint32_t clearValueCount;
667 DE_NULL // const VkClearValue* pClearValues;
668 };
669 VkDeviceSize vertexBufferOffset = 0u;
670
671 vkd.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
672 vkd.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
673 vkd.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
674 &descriptorSet.get(), 0u, DE_NULL);
675 vkd.cmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
676 vkd.cmdDraw(commandBuffer, uint32_t(vertices.size()), 1, 0, 0);
677 vkd.cmdEndRenderPass(commandBuffer);
678 }
679
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)680 bool GraphicsConfiguration::verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams)
681 {
682 // create result image
683 const bool allMiss = (testParams.emptyASCase != EmptyAccelerationStructureCase::NOT_EMPTY);
684 tcu::TextureFormat imageFormat = vk::mapVkFormat(getResultImageFormat());
685 tcu::ConstPixelBufferAccess resultAccess(imageFormat, testParams.width, testParams.height, 2,
686 resultBuffer->getAllocation().getHostPtr());
687
688 // create reference image
689 std::vector<uint32_t> reference(testParams.width * testParams.height * 2);
690 tcu::PixelBufferAccess referenceAccess(imageFormat, testParams.width, testParams.height, 2, reference.data());
691
692 std::vector<std::vector<uint32_t>> primitives = {{0, 1, 2}, {1, 3, 2}};
693
694 tcu::UVec4 hitValue0 = tcu::UVec4(1, 0, 0, 0);
695 tcu::UVec4 hitValue1 = tcu::UVec4(1, 0, 0, 0);
696 tcu::UVec4 missValue = tcu::UVec4(0, 0, 0, 0);
697 tcu::UVec4 clearValue = tcu::UVec4(0xFF, 0, 0, 0);
698
699 switch (testParams.shaderSourceType)
700 {
701 case SST_VERTEX_SHADER:
702 tcu::clear(referenceAccess, clearValue);
703 for (uint32_t vertexNdx = 0; vertexNdx < 4; ++vertexNdx)
704 {
705 if (!allMiss && (vertexNdx == 1 || vertexNdx == 2))
706 {
707 referenceAccess.setPixel(hitValue0, vertexNdx, 0, 0);
708 referenceAccess.setPixel(hitValue1, vertexNdx, 0, 1);
709 }
710 else
711 {
712 referenceAccess.setPixel(missValue, vertexNdx, 0, 0);
713 referenceAccess.setPixel(missValue, vertexNdx, 0, 1);
714 }
715 }
716 break;
717 case SST_TESSELATION_EVALUATION_SHADER:
718 case SST_TESSELATION_CONTROL_SHADER:
719 case SST_GEOMETRY_SHADER:
720 tcu::clear(referenceAccess, clearValue);
721 for (uint32_t primitiveNdx = 0; primitiveNdx < primitives.size(); ++primitiveNdx)
722 for (uint32_t vertexNdx = 0; vertexNdx < 3; ++vertexNdx)
723 {
724 uint32_t vNdx = primitives[primitiveNdx][vertexNdx];
725 if (!allMiss && (vNdx == 1 || vNdx == 2))
726 {
727 referenceAccess.setPixel(hitValue0, primitiveNdx, vertexNdx, 0);
728 referenceAccess.setPixel(hitValue1, primitiveNdx, vertexNdx, 1);
729 }
730 else
731 {
732 referenceAccess.setPixel(missValue, primitiveNdx, vertexNdx, 0);
733 referenceAccess.setPixel(missValue, primitiveNdx, vertexNdx, 1);
734 }
735 }
736 break;
737 case SST_FRAGMENT_SHADER:
738 tcu::clear(referenceAccess, missValue);
739 for (uint32_t y = 0; y < testParams.height; ++y)
740 for (uint32_t x = 0; x < testParams.width; ++x)
741 {
742 if (allMiss || ((x + y) % 2) == 0)
743 continue;
744
745 referenceAccess.setPixel(hitValue0, x, y, 0);
746 referenceAccess.setPixel(hitValue1, x, y, 1);
747 }
748 break;
749 default:
750 TCU_THROW(InternalError, "Wrong shader source type");
751 }
752
753 // compare result and reference
754 return tcu::intThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess,
755 resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
756 }
757
getResultImageFormat()758 VkFormat GraphicsConfiguration::getResultImageFormat()
759 {
760 return VK_FORMAT_R32_UINT;
761 }
762
getResultImageFormatSize()763 size_t GraphicsConfiguration::getResultImageFormatSize()
764 {
765 return sizeof(uint32_t);
766 }
767
getClearValue()768 VkClearValue GraphicsConfiguration::getClearValue()
769 {
770 return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
771 }
772
773 class ComputeConfiguration : public TestConfiguration
774 {
775 public:
776 virtual ~ComputeConfiguration();
777 void initConfiguration(Context &context, TestParams &testParams) override;
778 void fillCommandBuffer(
779 Context &context, TestParams &testParams, VkCommandBuffer commandBuffer,
780 const VkWriteDescriptorSetAccelerationStructureKHR &rayQueryAccelerationStructureWriteDescriptorSet,
781 const VkDescriptorImageInfo &resultImageInfo) override;
782 bool verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams) override;
783 VkFormat getResultImageFormat() override;
784 size_t getResultImageFormatSize() override;
785 VkClearValue getClearValue() override;
786
787 protected:
788 Move<VkDescriptorSetLayout> descriptorSetLayout;
789 Move<VkDescriptorPool> descriptorPool;
790 Move<VkDescriptorSet> descriptorSet;
791 Move<VkPipelineLayout> pipelineLayout;
792 Move<VkShaderModule> shaderModule;
793 Move<VkPipeline> pipeline;
794 };
795
~ComputeConfiguration()796 ComputeConfiguration::~ComputeConfiguration()
797 {
798 }
799
initConfiguration(Context & context,TestParams & testParams)800 void ComputeConfiguration::initConfiguration(Context &context, TestParams &testParams)
801 {
802 const DeviceInterface &vkd = context.getDeviceInterface();
803 const VkDevice device = context.getDevice();
804
805 descriptorSetLayout =
806 DescriptorSetLayoutBuilder()
807 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
808 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_COMPUTE_BIT)
809 .build(vkd, device);
810 descriptorPool = DescriptorPoolBuilder()
811 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
812 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
813 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
814 descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
815 pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
816
817 std::vector<std::string> rayQueryTestName;
818 rayQueryTestName.push_back("comp_as_triangle");
819 rayQueryTestName.push_back("comp_as_aabb");
820
821 const auto bottomTestTypeIdx = static_cast<int>(testParams.bottomTestType);
822 shaderModule =
823 createShaderModule(vkd, device, context.getBinaryCollection().get(rayQueryTestName[bottomTestTypeIdx]), 0u);
824 const VkPipelineShaderStageCreateInfo pipelineShaderStageParams = {
825 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
826 DE_NULL, // const void* pNext;
827 0u, // VkPipelineShaderStageCreateFlags flags;
828 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
829 *shaderModule, // VkShaderModule module;
830 "main", // const char* pName;
831 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
832 };
833 const VkComputePipelineCreateInfo pipelineCreateInfo = {
834 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
835 DE_NULL, // const void* pNext;
836 0u, // VkPipelineCreateFlags flags;
837 pipelineShaderStageParams, // VkPipelineShaderStageCreateInfo stage;
838 *pipelineLayout, // VkPipelineLayout layout;
839 DE_NULL, // VkPipeline basePipelineHandle;
840 0, // int32_t basePipelineIndex;
841 };
842
843 pipeline = createComputePipeline(vkd, device, DE_NULL, &pipelineCreateInfo);
844 }
845
fillCommandBuffer(Context & context,TestParams & testParams,VkCommandBuffer commandBuffer,const VkWriteDescriptorSetAccelerationStructureKHR & rayQueryAccelerationStructureWriteDescriptorSet,const VkDescriptorImageInfo & resultImageInfo)846 void ComputeConfiguration::fillCommandBuffer(
847 Context &context, TestParams &testParams, VkCommandBuffer commandBuffer,
848 const VkWriteDescriptorSetAccelerationStructureKHR &rayQueryAccelerationStructureWriteDescriptorSet,
849 const VkDescriptorImageInfo &resultImageInfo)
850 {
851 const DeviceInterface &vkd = context.getDeviceInterface();
852 const VkDevice device = context.getDevice();
853
854 DescriptorSetUpdateBuilder()
855 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
856 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo)
857 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
858 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet)
859 .update(vkd, device);
860
861 vkd.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
862
863 vkd.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u,
864 &descriptorSet.get(), 0u, DE_NULL);
865
866 vkd.cmdDispatch(commandBuffer, testParams.width, testParams.height, 1);
867 }
868
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)869 bool ComputeConfiguration::verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams)
870 {
871 // create result image
872 const bool allMiss = (testParams.emptyASCase != EmptyAccelerationStructureCase::NOT_EMPTY);
873 tcu::TextureFormat imageFormat = vk::mapVkFormat(getResultImageFormat());
874 tcu::ConstPixelBufferAccess resultAccess(imageFormat, testParams.width, testParams.height, 2,
875 resultBuffer->getAllocation().getHostPtr());
876
877 // create reference image
878 std::vector<uint32_t> reference(testParams.width * testParams.height * 2);
879 tcu::PixelBufferAccess referenceAccess(imageFormat, testParams.width, testParams.height, 2, reference.data());
880
881 tcu::UVec4 hitValue0 = tcu::UVec4(1, 0, 0, 0);
882 tcu::UVec4 hitValue1 = tcu::UVec4(1, 0, 0, 0);
883 tcu::UVec4 missValue = tcu::UVec4(0, 0, 0, 0);
884
885 tcu::clear(referenceAccess, missValue);
886
887 for (uint32_t y = 0; y < testParams.height; ++y)
888 for (uint32_t x = 0; x < testParams.width; ++x)
889 {
890 if (allMiss || ((x + y) % 2) == 0)
891 continue;
892
893 referenceAccess.setPixel(hitValue0, x, y, 0);
894 referenceAccess.setPixel(hitValue1, x, y, 1);
895 }
896
897 // compare result and reference
898 return tcu::intThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess,
899 resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
900 }
901
getResultImageFormat()902 VkFormat ComputeConfiguration::getResultImageFormat()
903 {
904 return VK_FORMAT_R32_UINT;
905 }
906
getResultImageFormatSize()907 size_t ComputeConfiguration::getResultImageFormatSize()
908 {
909 return sizeof(uint32_t);
910 }
911
getClearValue()912 VkClearValue ComputeConfiguration::getClearValue()
913 {
914 return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
915 }
916
917 class RayTracingConfiguration : public TestConfiguration
918 {
919 public:
920 virtual ~RayTracingConfiguration();
921 void initConfiguration(Context &context, TestParams &testParams) override;
922 void fillCommandBuffer(
923 Context &context, TestParams &testParams, VkCommandBuffer commandBuffer,
924 const VkWriteDescriptorSetAccelerationStructureKHR &rayQueryAccelerationStructureWriteDescriptorSet,
925 const VkDescriptorImageInfo &resultImageInfo) override;
926 bool verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams) override;
927 VkFormat getResultImageFormat() override;
928 size_t getResultImageFormatSize() override;
929 VkClearValue getClearValue() override;
930
931 protected:
932 Move<VkDescriptorSetLayout> descriptorSetLayout;
933 Move<VkDescriptorPool> descriptorPool;
934 Move<VkDescriptorSet> descriptorSet;
935 Move<VkPipelineLayout> pipelineLayout;
936
937 de::MovePtr<RayTracingPipeline> rayTracingPipeline;
938 Move<VkPipeline> rtPipeline;
939
940 de::MovePtr<BufferWithMemory> raygenShaderBindingTable;
941 de::MovePtr<BufferWithMemory> hitShaderBindingTable;
942 de::MovePtr<BufferWithMemory> missShaderBindingTable;
943 de::MovePtr<BufferWithMemory> callableShaderBindingTable;
944
945 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures;
946 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
947 };
948
~RayTracingConfiguration()949 RayTracingConfiguration::~RayTracingConfiguration()
950 {
951 }
952
initConfiguration(Context & context,TestParams & testParams)953 void RayTracingConfiguration::initConfiguration(Context &context, TestParams &testParams)
954 {
955 const InstanceInterface &vki = context.getInstanceInterface();
956 const DeviceInterface &vkd = context.getDeviceInterface();
957 const VkDevice device = context.getDevice();
958 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
959 Allocator &allocator = context.getDefaultAllocator();
960
961 descriptorSetLayout = DescriptorSetLayoutBuilder()
962 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
963 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
964 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
965 .build(vkd, device);
966 descriptorPool = DescriptorPoolBuilder()
967 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
968 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
969 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
970 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
971 descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
972 pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
973
974 rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
975
976 const std::map<ShaderSourceType, std::vector<std::string>> shaderNames = {
977 //idx: 0 1 2 3 4 5
978 //shader: rgen, isect, ahit, chit, miss, call
979 //group: 0 1 1 1 2 3
980 {SST_RAY_GENERATION_SHADER, {"rgen_%s", "", "", "", "", ""}},
981 {SST_INTERSECTION_SHADER, {"rgen", "isect_%s", "", "chit_isect", "miss", ""}},
982 {SST_ANY_HIT_SHADER, {"rgen", "isect", "ahit_%s", "", "miss", ""}},
983 {SST_CLOSEST_HIT_SHADER, {"rgen", "isect", "", "chit_%s", "miss", ""}},
984 {SST_MISS_SHADER, {"rgen", "isect", "", "chit", "miss_%s", ""}},
985 {SST_CALLABLE_SHADER, {"rgen_call", "", "", "chit", "miss", "call_%s"}},
986 };
987
988 std::vector<std::string> rayQueryTestName;
989 rayQueryTestName.push_back("as_triangle");
990 rayQueryTestName.push_back("as_aabb");
991
992 auto shaderNameIt = shaderNames.find(testParams.shaderSourceType);
993 if (shaderNameIt == end(shaderNames))
994 TCU_THROW(InternalError, "Wrong shader source type");
995
996 bool rgenX, isectX, ahitX, chitX, missX, callX;
997 const auto bottomTestTypeIdx = static_cast<int>(testParams.bottomTestType);
998 rgenX = registerShaderModule(vkd, device, context, *rayTracingPipeline, VK_SHADER_STAGE_RAYGEN_BIT_KHR,
999 shaderNameIt->second[0], rayQueryTestName[bottomTestTypeIdx], 0);
1000 if (testParams.shaderSourceType == SST_INTERSECTION_SHADER)
1001 isectX = registerShaderModule(vkd, device, context, *rayTracingPipeline, VK_SHADER_STAGE_INTERSECTION_BIT_KHR,
1002 shaderNameIt->second[1], rayQueryTestName[bottomTestTypeIdx], 1);
1003 else
1004 isectX = false;
1005 ahitX = registerShaderModule(vkd, device, context, *rayTracingPipeline, VK_SHADER_STAGE_ANY_HIT_BIT_KHR,
1006 shaderNameIt->second[2], rayQueryTestName[bottomTestTypeIdx], 1);
1007 chitX = registerShaderModule(vkd, device, context, *rayTracingPipeline, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
1008 shaderNameIt->second[3], rayQueryTestName[bottomTestTypeIdx], 1);
1009 missX = registerShaderModule(vkd, device, context, *rayTracingPipeline, VK_SHADER_STAGE_MISS_BIT_KHR,
1010 shaderNameIt->second[4], rayQueryTestName[bottomTestTypeIdx], 2);
1011 callX = registerShaderModule(vkd, device, context, *rayTracingPipeline, VK_SHADER_STAGE_CALLABLE_BIT_KHR,
1012 shaderNameIt->second[5], rayQueryTestName[bottomTestTypeIdx], 3);
1013 bool hitX = isectX || ahitX || chitX;
1014
1015 rtPipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
1016
1017 uint32_t shaderGroupHandleSize = getShaderGroupHandleSize(vki, physicalDevice);
1018 uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
1019
1020 if (rgenX)
1021 raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
1022 vkd, device, *rtPipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
1023 if (hitX)
1024 hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
1025 vkd, device, *rtPipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
1026 if (missX)
1027 missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
1028 vkd, device, *rtPipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
1029 if (callX)
1030 callableShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
1031 vkd, device, *rtPipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 3, 1);
1032 }
1033
fillCommandBuffer(Context & context,TestParams & testParams,VkCommandBuffer commandBuffer,const VkWriteDescriptorSetAccelerationStructureKHR & rayQueryAccelerationStructureWriteDescriptorSet,const VkDescriptorImageInfo & resultImageInfo)1034 void RayTracingConfiguration::fillCommandBuffer(
1035 Context &context, TestParams &testParams, VkCommandBuffer commandBuffer,
1036 const VkWriteDescriptorSetAccelerationStructureKHR &rayQueryAccelerationStructureWriteDescriptorSet,
1037 const VkDescriptorImageInfo &resultImageInfo)
1038 {
1039 const InstanceInterface &vki = context.getInstanceInterface();
1040 const DeviceInterface &vkd = context.getDeviceInterface();
1041 const VkDevice device = context.getDevice();
1042 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1043 Allocator &allocator = context.getDefaultAllocator();
1044
1045 {
1046 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
1047 makeBottomLevelAccelerationStructure();
1048 bottomLevelAccelerationStructure->setGeometryCount(1);
1049
1050 de::SharedPtr<RaytracedGeometryBase> geometry;
1051 if (testParams.shaderSourceType != SST_INTERSECTION_SHADER)
1052 {
1053 tcu::Vec3 v0(0.0f, float(testParams.height), 0.0f);
1054 tcu::Vec3 v1(0.0f, 0.0f, 0.0f);
1055 tcu::Vec3 v2(float(testParams.width), float(testParams.height), 0.0f);
1056 tcu::Vec3 v3(float(testParams.width), 0.0f, 0.0f);
1057 tcu::Vec3 missOffset(0.0f, 0.0f, 0.0f);
1058 if (testParams.shaderSourceType == SST_MISS_SHADER)
1059 missOffset = tcu::Vec3(1.0f + float(testParams.width), 0.0f, 0.0f);
1060
1061 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_FORMAT_R32G32B32_SFLOAT,
1062 VK_INDEX_TYPE_NONE_KHR);
1063 geometry->addVertex(v0 + missOffset);
1064 geometry->addVertex(v1 + missOffset);
1065 geometry->addVertex(v2 + missOffset);
1066 geometry->addVertex(v2 + missOffset);
1067 geometry->addVertex(v1 + missOffset);
1068 geometry->addVertex(v3 + missOffset);
1069 }
1070 else // testParams.shaderSourceType == SST_INTERSECTION_SHADER
1071 {
1072 tcu::Vec3 v0(0.0f, 0.0f, -0.1f);
1073 tcu::Vec3 v1(float(testParams.width), float(testParams.height), 0.1f);
1074
1075 geometry =
1076 makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
1077 geometry->addVertex(v0);
1078 geometry->addVertex(v1);
1079 }
1080 bottomLevelAccelerationStructure->addGeometry(geometry);
1081 bottomLevelAccelerationStructures.push_back(
1082 de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
1083
1084 for (auto &blas : bottomLevelAccelerationStructures)
1085 blas->createAndBuild(vkd, device, commandBuffer, allocator);
1086 }
1087
1088 topLevelAccelerationStructure = makeTopLevelAccelerationStructure();
1089 topLevelAccelerationStructure->setInstanceCount(1);
1090 topLevelAccelerationStructure->addInstance(bottomLevelAccelerationStructures[0]);
1091 topLevelAccelerationStructure->createAndBuild(vkd, device, commandBuffer, allocator);
1092
1093 const TopLevelAccelerationStructure *topLevelAccelerationStructurePtr = topLevelAccelerationStructure.get();
1094 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
1095 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
1096 DE_NULL, // const void* pNext;
1097 1u, // uint32_t accelerationStructureCount;
1098 topLevelAccelerationStructurePtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
1099 };
1100
1101 DescriptorSetUpdateBuilder()
1102 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1103 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo)
1104 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
1105 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
1106 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u),
1107 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet)
1108 .update(vkd, device);
1109
1110 vkd.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
1111 &descriptorSet.get(), 0, DE_NULL);
1112
1113 vkd.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *rtPipeline);
1114
1115 uint32_t shaderGroupHandleSize = getShaderGroupHandleSize(vki, physicalDevice);
1116 VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
1117 raygenShaderBindingTable.get() != DE_NULL ?
1118 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0),
1119 shaderGroupHandleSize, shaderGroupHandleSize) :
1120 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1121 VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
1122 hitShaderBindingTable.get() != DE_NULL ?
1123 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0),
1124 shaderGroupHandleSize, shaderGroupHandleSize) :
1125 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1126 VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion =
1127 missShaderBindingTable.get() != DE_NULL ?
1128 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0),
1129 shaderGroupHandleSize, shaderGroupHandleSize) :
1130 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1131 VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion =
1132 callableShaderBindingTable.get() != DE_NULL ?
1133 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, callableShaderBindingTable->get(), 0),
1134 shaderGroupHandleSize, shaderGroupHandleSize) :
1135 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1136
1137 cmdTraceRays(vkd, commandBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
1138 &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, testParams.width, testParams.height,
1139 1);
1140 }
1141
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)1142 bool RayTracingConfiguration::verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams)
1143 {
1144 // create result image
1145 const bool allMiss = (testParams.emptyASCase != EmptyAccelerationStructureCase::NOT_EMPTY);
1146 tcu::TextureFormat imageFormat = vk::mapVkFormat(getResultImageFormat());
1147 tcu::ConstPixelBufferAccess resultAccess(imageFormat, testParams.width, testParams.height, 2,
1148 resultBuffer->getAllocation().getHostPtr());
1149
1150 // create reference image
1151 std::vector<uint32_t> reference(testParams.width * testParams.height * 2);
1152 tcu::PixelBufferAccess referenceAccess(imageFormat, testParams.width, testParams.height, 2, reference.data());
1153
1154 tcu::UVec4 missValue(0, 0, 0, 0);
1155 tcu::UVec4 hitValue(1, 0, 0, 0);
1156
1157 for (uint32_t y = 0; y < testParams.height; ++y)
1158 for (uint32_t x = 0; x < testParams.width; ++x)
1159 {
1160 if (allMiss || ((x + y) % 2) == 0)
1161 {
1162 referenceAccess.setPixel(missValue, x, y, 0);
1163 referenceAccess.setPixel(missValue, x, y, 1);
1164 }
1165 else
1166 {
1167 referenceAccess.setPixel(hitValue, x, y, 0);
1168 referenceAccess.setPixel(hitValue, x, y, 1);
1169 }
1170 }
1171
1172 // compare result and reference
1173 return tcu::intThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess,
1174 resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
1175 }
1176
getResultImageFormat()1177 VkFormat RayTracingConfiguration::getResultImageFormat()
1178 {
1179 return VK_FORMAT_R32_UINT;
1180 }
1181
getResultImageFormatSize()1182 size_t RayTracingConfiguration::getResultImageFormatSize()
1183 {
1184 return sizeof(uint32_t);
1185 }
1186
getClearValue()1187 VkClearValue RayTracingConfiguration::getClearValue()
1188 {
1189 return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
1190 }
1191
createTestConfiguration(const ShaderSourcePipeline & shaderSourcePipeline)1192 de::SharedPtr<TestConfiguration> createTestConfiguration(const ShaderSourcePipeline &shaderSourcePipeline)
1193 {
1194 switch (shaderSourcePipeline)
1195 {
1196 case SSP_GRAPHICS_PIPELINE:
1197 return de::SharedPtr<TestConfiguration>(new GraphicsConfiguration());
1198 case SSP_COMPUTE_PIPELINE:
1199 return de::SharedPtr<TestConfiguration>(new ComputeConfiguration());
1200 case SSP_RAY_TRACING_PIPELINE:
1201 return de::SharedPtr<TestConfiguration>(new RayTracingConfiguration());
1202 default:
1203 TCU_THROW(InternalError, "Wrong shader source pipeline");
1204 }
1205 return de::SharedPtr<TestConfiguration>();
1206 }
1207
1208 class CheckerboardSceneBuilder : public SceneBuilder
1209 {
1210 public:
1211 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
1212 Context &context, TestParams &testParams) override;
1213 de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
1214 Context &context, TestParams &testParams,
1215 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) override;
1216 };
1217
initBottomAccelerationStructures(Context & context,TestParams & testParams)1218 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> CheckerboardSceneBuilder::initBottomAccelerationStructures(
1219 Context &context, TestParams &testParams)
1220 {
1221 DE_UNREF(context);
1222
1223 // Cull flags can only be used with triangles.
1224 DE_ASSERT(testParams.cullFlags == InstanceCullFlags::NONE ||
1225 testParams.bottomTestType == BottomTestType::TRIANGLES);
1226
1227 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> result;
1228
1229 const auto instanceFlags = getCullFlags(testParams.cullFlags);
1230
1231 tcu::Vec3 v0(0.0, 1.0, 0.0);
1232 tcu::Vec3 v1(0.0, 0.0, 0.0);
1233 tcu::Vec3 v2(1.0, 1.0, 0.0);
1234 tcu::Vec3 v3(1.0, 0.0, 0.0);
1235
1236 // Different vertex configurations of a triangle whose parameter x is set to NaN during inactive_triangles tests
1237 const bool nanConfig[4][4] = {
1238 {true, true, true, true},
1239 {false, true, true, false},
1240 {false, false, true, false},
1241 {false, true, false, false},
1242 };
1243
1244 unsigned int geometryCount = testParams.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_TRIANGLES ? 4U : 1U;
1245
1246 if (testParams.topTestType == TopTestType::DIFFERENT_INSTANCES)
1247 {
1248 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
1249 makeBottomLevelAccelerationStructure();
1250 bottomLevelAccelerationStructure->setGeometryCount(1u);
1251 de::SharedPtr<RaytracedGeometryBase> geometry;
1252 if (testParams.bottomTestType == BottomTestType::TRIANGLES)
1253 {
1254 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat,
1255 testParams.indexType, testParams.padVertices);
1256 if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
1257 {
1258 if (instanceFlags == 0u)
1259 {
1260 geometry->addVertex(v0);
1261 geometry->addVertex(v1);
1262 geometry->addVertex(v2);
1263 geometry->addVertex(v2);
1264 geometry->addVertex(v1);
1265 geometry->addVertex(v3);
1266 }
1267 else // Counterclockwise so the flags will be needed for the geometry to be visible.
1268 {
1269 geometry->addVertex(v2);
1270 geometry->addVertex(v1);
1271 geometry->addVertex(v0);
1272 geometry->addVertex(v3);
1273 geometry->addVertex(v1);
1274 geometry->addVertex(v2);
1275 }
1276 }
1277 else // m_data.indexType != VK_INDEX_TYPE_NONE_KHR
1278 {
1279 geometry->addVertex(v0);
1280 geometry->addVertex(v1);
1281 geometry->addVertex(v2);
1282 geometry->addVertex(v3);
1283
1284 if (instanceFlags == 0u)
1285 {
1286 geometry->addIndex(0);
1287 geometry->addIndex(1);
1288 geometry->addIndex(2);
1289 geometry->addIndex(2);
1290 geometry->addIndex(1);
1291 geometry->addIndex(3);
1292 }
1293 else // Counterclockwise so the flags will be needed for the geometry to be visible.
1294 {
1295 geometry->addIndex(2);
1296 geometry->addIndex(1);
1297 geometry->addIndex(0);
1298 geometry->addIndex(3);
1299 geometry->addIndex(1);
1300 geometry->addIndex(2);
1301 }
1302 }
1303 }
1304 else // m_data.bottomTestType == BTT_AABBS
1305 {
1306 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat, testParams.indexType,
1307 testParams.padVertices);
1308
1309 if (!testParams.padVertices)
1310 {
1311 // Single AABB.
1312 geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
1313 geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f));
1314 }
1315 else
1316 {
1317 // Multiple AABBs covering the same space.
1318 geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
1319 geometry->addVertex(tcu::Vec3(0.5f, 0.5f, 0.1f));
1320
1321 geometry->addVertex(tcu::Vec3(0.5f, 0.5f, -0.1f));
1322 geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f));
1323
1324 geometry->addVertex(tcu::Vec3(0.0f, 0.5f, -0.1f));
1325 geometry->addVertex(tcu::Vec3(0.5f, 1.0f, 0.1f));
1326
1327 geometry->addVertex(tcu::Vec3(0.5f, 0.0f, -0.1f));
1328 geometry->addVertex(tcu::Vec3(1.0f, 0.5f, 0.1f));
1329 }
1330 }
1331
1332 bottomLevelAccelerationStructure->addGeometry(geometry);
1333 result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
1334 }
1335 else // m_data.topTestType == TTT_IDENTICAL_INSTANCES
1336 {
1337 tcu::TextureFormat texFormat = mapVkFormat(testParams.vertexFormat);
1338 tcu::Vec3 scale(1.0f, 1.0f, 1.0f);
1339 if (tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT)
1340 scale = tcu::Vec3(1.0f / float(testParams.width), 1.0f / float(testParams.height), 1.0f);
1341
1342 // triangle and aabb tests use geometries/aabbs with different vertex positions and the same identity matrix in each instance data
1343 for (uint32_t y = 0; y < testParams.height; ++y)
1344 for (uint32_t x = 0; x < testParams.width; ++x)
1345 {
1346 // let's build a chessboard of geometries
1347 if (((x + y) % 2) == 0)
1348 continue;
1349 tcu::Vec3 xyz((float)x, (float)y, 0.0f);
1350
1351 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
1352 makeBottomLevelAccelerationStructure();
1353 bottomLevelAccelerationStructure->setGeometryCount(geometryCount);
1354
1355 if (testParams.bottomTestType == BottomTestType::TRIANGLES)
1356 {
1357 for (unsigned int i = 0; i < geometryCount; i++)
1358 {
1359 de::SharedPtr<RaytracedGeometryBase> geometry;
1360 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat,
1361 testParams.indexType, testParams.padVertices);
1362
1363 if (testParams.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_TRIANGLES)
1364 {
1365 const auto nanValue = tcu::Float32::nan().asFloat();
1366
1367 if (nanConfig[i][0])
1368 v0.x() = nanValue;
1369 if (nanConfig[i][1])
1370 v1.x() = nanValue;
1371 if (nanConfig[i][2])
1372 v2.x() = nanValue;
1373 if (nanConfig[i][3])
1374 v3.x() = nanValue;
1375 }
1376
1377 if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
1378 {
1379 if (instanceFlags == 0u)
1380 {
1381 geometry->addVertex(scale * (xyz + v0));
1382 geometry->addVertex(scale * (xyz + v1));
1383 geometry->addVertex(scale * (xyz + v2));
1384 geometry->addVertex(scale * (xyz + v2));
1385 geometry->addVertex(scale * (xyz + v1));
1386 geometry->addVertex(scale * (xyz + v3));
1387 }
1388 else // Counterclockwise so the flags will be needed for the geometry to be visible.
1389 {
1390 geometry->addVertex(scale * (xyz + v2));
1391 geometry->addVertex(scale * (xyz + v1));
1392 geometry->addVertex(scale * (xyz + v0));
1393 geometry->addVertex(scale * (xyz + v3));
1394 geometry->addVertex(scale * (xyz + v1));
1395 geometry->addVertex(scale * (xyz + v2));
1396 }
1397 }
1398
1399 else
1400 {
1401 geometry->addVertex(scale * (xyz + v0));
1402 geometry->addVertex(scale * (xyz + v1));
1403 geometry->addVertex(scale * (xyz + v2));
1404 geometry->addVertex(scale * (xyz + v3));
1405
1406 if (instanceFlags == 0u)
1407 {
1408 geometry->addIndex(0);
1409 geometry->addIndex(1);
1410 geometry->addIndex(2);
1411 geometry->addIndex(2);
1412 geometry->addIndex(1);
1413 geometry->addIndex(3);
1414 }
1415 else // Counterclockwise so the flags will be needed for the geometry to be visible.
1416 {
1417 geometry->addIndex(2);
1418 geometry->addIndex(1);
1419 geometry->addIndex(0);
1420 geometry->addIndex(3);
1421 geometry->addIndex(1);
1422 geometry->addIndex(2);
1423 }
1424 }
1425
1426 bottomLevelAccelerationStructure->addGeometry(geometry);
1427 }
1428 }
1429 else // testParams.bottomTestType == BTT_AABBS
1430 {
1431 de::SharedPtr<RaytracedGeometryBase> geometry;
1432 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat,
1433 testParams.indexType, testParams.padVertices);
1434
1435 if (!testParams.padVertices)
1436 {
1437 // Single AABB.
1438 geometry->addVertex(scale * (xyz + tcu::Vec3(0.0f, 0.0f, -0.1f)));
1439 geometry->addVertex(scale * (xyz + tcu::Vec3(1.0f, 1.0f, 0.1f)));
1440 }
1441 else
1442 {
1443 // Multiple AABBs covering the same space.
1444 geometry->addVertex(scale * (xyz + tcu::Vec3(0.0f, 0.0f, -0.1f)));
1445 geometry->addVertex(scale * (xyz + tcu::Vec3(0.5f, 0.5f, 0.1f)));
1446
1447 geometry->addVertex(scale * (xyz + tcu::Vec3(0.5f, 0.5f, -0.1f)));
1448 geometry->addVertex(scale * (xyz + tcu::Vec3(1.0f, 1.0f, 0.1f)));
1449
1450 geometry->addVertex(scale * (xyz + tcu::Vec3(0.0f, 0.5f, -0.1f)));
1451 geometry->addVertex(scale * (xyz + tcu::Vec3(0.5f, 1.0f, 0.1f)));
1452
1453 geometry->addVertex(scale * (xyz + tcu::Vec3(0.5f, 0.0f, -0.1f)));
1454 geometry->addVertex(scale * (xyz + tcu::Vec3(1.0f, 0.5f, 0.1f)));
1455 }
1456
1457 bottomLevelAccelerationStructure->addGeometry(geometry);
1458 }
1459
1460 result.push_back(
1461 de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
1462 }
1463 }
1464
1465 return result;
1466 }
1467
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)1468 de::MovePtr<TopLevelAccelerationStructure> CheckerboardSceneBuilder::initTopAccelerationStructure(
1469 Context &context, TestParams &testParams,
1470 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures)
1471 {
1472 DE_UNREF(context);
1473
1474 const auto instanceCount = testParams.width * testParams.height / 2u;
1475 const auto instanceFlags = getCullFlags(testParams.cullFlags);
1476
1477 de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
1478 result->setInstanceCount(instanceCount);
1479
1480 if (testParams.topTestType == TopTestType::DIFFERENT_INSTANCES)
1481 {
1482
1483 for (uint32_t y = 0; y < testParams.height; ++y)
1484 for (uint32_t x = 0; x < testParams.width; ++x)
1485 {
1486 if (((x + y) % 2) == 0)
1487 continue;
1488 const VkTransformMatrixKHR transformMatrixKHR = {{
1489 // float matrix[3][4];
1490 {1.0f, 0.0f, 0.0f, (float)x},
1491 {0.0f, 1.0f, 0.0f, (float)y},
1492 {0.0f, 0.0f, 1.0f, 0.0f},
1493 }};
1494 result->addInstance(bottomLevelAccelerationStructures[0], transformMatrixKHR, 0u, 0xFFu, 0u,
1495 instanceFlags);
1496 }
1497 }
1498 else // testParams.topTestType == TTT_IDENTICAL_INSTANCES
1499 {
1500 tcu::TextureFormat texFormat = mapVkFormat(testParams.vertexFormat);
1501 tcu::Vec3 scale(1.0f, 1.0f, 1.0f);
1502 if (tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT)
1503 scale = tcu::Vec3(float(testParams.width), float(testParams.height), 1.0f);
1504
1505 const VkTransformMatrixKHR transformMatrixKHR = {{
1506 // float matrix[3][4];
1507 {scale.x(), 0.0f, 0.0f, 0.0f},
1508 {0.0f, scale.y(), 0.0f, 0.0f},
1509 {0.0f, 0.0f, scale.z(), 0.0f},
1510 }};
1511
1512 uint32_t currentInstanceIndex = 0;
1513
1514 for (uint32_t y = 0; y < testParams.height; ++y)
1515 for (uint32_t x = 0; x < testParams.width; ++x)
1516 {
1517 if (((x + y) % 2) == 0)
1518 continue;
1519 result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++], transformMatrixKHR, 0u,
1520 0xFFu, 0u, instanceFlags);
1521 }
1522 }
1523
1524 return result;
1525 }
1526
commonASTestsCheckSupport(Context & context)1527 void commonASTestsCheckSupport(Context &context)
1528 {
1529 context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
1530 context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
1531 context.requireDeviceFunctionality("VK_KHR_ray_query");
1532
1533 const VkPhysicalDeviceRayQueryFeaturesKHR &rayQueryFeaturesKHR = context.getRayQueryFeatures();
1534 if (rayQueryFeaturesKHR.rayQuery == false)
1535 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayQueryFeaturesKHR.rayQuery");
1536
1537 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
1538 context.getAccelerationStructureFeatures();
1539 if (accelerationStructureFeaturesKHR.accelerationStructure == false)
1540 TCU_THROW(TestError,
1541 "VK_KHR_ray_query requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
1542 }
1543
1544 class RayQueryASBasicTestCase : public TestCase
1545 {
1546 public:
1547 RayQueryASBasicTestCase(tcu::TestContext &context, const char *name, const TestParams &data);
1548 ~RayQueryASBasicTestCase(void);
1549
1550 virtual void checkSupport(Context &context) const;
1551 virtual void initPrograms(SourceCollections &programCollection) const;
1552 virtual TestInstance *createInstance(Context &context) const;
1553
1554 protected:
1555 TestParams m_data;
1556 };
1557
1558 class RayQueryASFuncArgTestCase : public RayQueryASBasicTestCase
1559 {
1560 public:
1561 RayQueryASFuncArgTestCase(tcu::TestContext &context, const char *name, const TestParams &data);
~RayQueryASFuncArgTestCase(void)1562 ~RayQueryASFuncArgTestCase(void)
1563 {
1564 }
1565
1566 virtual void initPrograms(SourceCollections &programCollection) const;
1567 };
1568
1569 class RayQueryASBasicTestInstance : public TestInstance
1570 {
1571 public:
1572 RayQueryASBasicTestInstance(Context &context, const TestParams &data);
1573 ~RayQueryASBasicTestInstance(void);
1574 tcu::TestStatus iterate(void);
1575
1576 protected:
1577 bool iterateNoWorkers(void);
1578 bool iterateWithWorkers(void);
1579 de::MovePtr<BufferWithMemory> runTest(TestConfiguration *testConfiguration, SceneBuilder *sceneBuilder,
1580 const uint32_t workerThreadsCount);
1581
1582 private:
1583 TestParams m_data;
1584 };
1585
RayQueryASBasicTestCase(tcu::TestContext & context,const char * name,const TestParams & data)1586 RayQueryASBasicTestCase::RayQueryASBasicTestCase(tcu::TestContext &context, const char *name, const TestParams &data)
1587 : vkt::TestCase(context, name)
1588 , m_data(data)
1589 {
1590 }
1591
~RayQueryASBasicTestCase(void)1592 RayQueryASBasicTestCase::~RayQueryASBasicTestCase(void)
1593 {
1594 }
1595
checkSupport(Context & context) const1596 void RayQueryASBasicTestCase::checkSupport(Context &context) const
1597 {
1598 commonASTestsCheckSupport(context);
1599
1600 const VkPhysicalDeviceFeatures2 &features2 = context.getDeviceFeatures2();
1601
1602 if ((m_data.shaderSourceType == SST_TESSELATION_CONTROL_SHADER ||
1603 m_data.shaderSourceType == SST_TESSELATION_EVALUATION_SHADER) &&
1604 features2.features.tessellationShader == false)
1605 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceFeatures2.tessellationShader");
1606
1607 if (m_data.shaderSourceType == SST_GEOMETRY_SHADER && features2.features.geometryShader == false)
1608 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceFeatures2.geometryShader");
1609
1610 if (m_data.shaderSourceType == SST_RAY_GENERATION_SHADER || m_data.shaderSourceType == SST_INTERSECTION_SHADER ||
1611 m_data.shaderSourceType == SST_ANY_HIT_SHADER || m_data.shaderSourceType == SST_CLOSEST_HIT_SHADER ||
1612 m_data.shaderSourceType == SST_MISS_SHADER || m_data.shaderSourceType == SST_CALLABLE_SHADER)
1613 {
1614 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
1615
1616 const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
1617 context.getRayTracingPipelineFeatures();
1618
1619 if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
1620 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
1621 }
1622
1623 switch (m_data.shaderSourceType)
1624 {
1625 case SST_VERTEX_SHADER:
1626 case SST_TESSELATION_CONTROL_SHADER:
1627 case SST_TESSELATION_EVALUATION_SHADER:
1628 case SST_GEOMETRY_SHADER:
1629 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
1630 break;
1631 default:
1632 break;
1633 }
1634
1635 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
1636 context.getAccelerationStructureFeatures();
1637 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR &&
1638 accelerationStructureFeaturesKHR.accelerationStructureHostCommands == false)
1639 TCU_THROW(NotSupportedError,
1640 "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
1641
1642 // Check supported vertex format.
1643 checkAccelerationStructureVertexBufferFormat(context.getInstanceInterface(), context.getPhysicalDevice(),
1644 m_data.vertexFormat);
1645 }
1646
initPrograms(SourceCollections & programCollection) const1647 void RayQueryASBasicTestCase::initPrograms(SourceCollections &programCollection) const
1648 {
1649 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1650
1651 // create parts of programs responsible for test execution
1652 std::vector<std::string> rayQueryTest;
1653 std::vector<std::string> rayQueryTestName;
1654 rayQueryTestName.push_back("as_triangle");
1655 rayQueryTestName.push_back("as_aabb");
1656
1657 {
1658 std::stringstream css;
1659 css << " float tmin = 0.0;\n"
1660 " float tmax = 1.0;\n"
1661 " vec3 direct = vec3(0.0, 0.0, -1.0);\n"
1662 " rayQueryEXT rq;\n"
1663 " rayQueryInitializeEXT(rq, rqTopLevelAS, "
1664 << ((m_data.cullFlags == InstanceCullFlags::NONE) ? "0" : "gl_RayFlagsCullBackFacingTrianglesEXT")
1665 << ", 0xFF, origin, tmin, direct, tmax);\n"
1666 " if(rayQueryProceedEXT(rq))\n"
1667 " {\n"
1668 " if (rayQueryGetIntersectionTypeEXT(rq, false)==gl_RayQueryCandidateIntersectionTriangleEXT)\n"
1669 " {\n"
1670 " hitValue.y = 1;\n"
1671 " hitValue.x = 1;\n"
1672 " }\n"
1673 " }\n";
1674 rayQueryTest.push_back(css.str());
1675 }
1676 {
1677 std::stringstream css;
1678 css << " float tmin = 0.0;\n"
1679 " float tmax = 1.0;\n"
1680 " vec3 direct = vec3(0.0, 0.0, -1.0);\n"
1681 " rayQueryEXT rq;\n"
1682 " rayQueryInitializeEXT(rq, rqTopLevelAS, 0, 0xFF, origin, tmin, direct, tmax);\n"
1683 " if(rayQueryProceedEXT(rq))\n"
1684 " {\n"
1685 " if (rayQueryGetIntersectionTypeEXT(rq, false)==gl_RayQueryCandidateIntersectionAABBEXT)\n"
1686 " {\n"
1687 " hitValue.y = 1;\n"
1688 " hitValue.x = 1;\n"
1689 " }\n"
1690 " }\n";
1691 rayQueryTest.push_back(css.str());
1692 }
1693
1694 const auto bottomTestTypeIdx = static_cast<int>(m_data.bottomTestType);
1695
1696 // create all programs
1697 if (m_data.shaderSourcePipeline == SSP_GRAPHICS_PIPELINE)
1698 {
1699 {
1700 std::stringstream css;
1701 css << "#version 460 core\n"
1702 "layout (location = 0) in vec3 position;\n"
1703 "out gl_PerVertex\n"
1704 "{\n"
1705 " vec4 gl_Position;\n"
1706 "};\n"
1707 "void main()\n"
1708 "{\n"
1709 " gl_Position = vec4(position, 1.0);\n"
1710 "}\n";
1711 programCollection.glslSources.add("vert") << glu::VertexSource(css.str()) << buildOptions;
1712 }
1713
1714 {
1715 std::stringstream css;
1716 css << "#version 460 core\n"
1717 "layout (location = 0) in vec3 position;\n"
1718 "out gl_PerVertex\n"
1719 "{\n"
1720 " vec4 gl_Position;\n"
1721 "};\n"
1722 "layout(location = 0) out int vertexIndex;\n"
1723 "void main()\n"
1724 "{\n"
1725 " gl_Position = vec4(position, 1.0);\n"
1726 " vertexIndex = gl_VertexIndex;\n"
1727 "}\n";
1728 programCollection.glslSources.add("vert_vid") << glu::VertexSource(css.str()) << buildOptions;
1729 }
1730
1731 {
1732 std::stringstream css;
1733 css << "#version 460 core\n"
1734 "#extension GL_EXT_ray_query : require\n"
1735 "layout (location = 0) in vec3 position;\n"
1736 "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1737 "layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
1738 "void main()\n"
1739 "{\n"
1740 " vec3 origin = vec3(float(position.x) + 0.5, float(position.y) + 0.5, 0.5);\n"
1741 " uvec4 hitValue = uvec4(0,0,0,0);\n"
1742 << rayQueryTest[bottomTestTypeIdx]
1743 << " imageStore(result, ivec3(gl_VertexIndex, 0, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1744 " imageStore(result, ivec3(gl_VertexIndex, 0, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1745 " gl_Position = vec4(position,1);\n"
1746 "}\n";
1747 std::stringstream cssName;
1748 cssName << "vert_" << rayQueryTestName[bottomTestTypeIdx];
1749
1750 programCollection.glslSources.add(cssName.str()) << glu::VertexSource(css.str()) << buildOptions;
1751 }
1752
1753 {
1754 std::stringstream css;
1755 css << "#version 460 core\n"
1756 "#extension GL_EXT_tessellation_shader : require\n"
1757 "in gl_PerVertex {\n"
1758 " vec4 gl_Position;\n"
1759 "} gl_in[];\n"
1760 "layout(vertices = 3) out;\n"
1761 "void main (void)\n"
1762 "{\n"
1763 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1764 " gl_TessLevelInner[0] = 1;\n"
1765 " gl_TessLevelOuter[0] = 1;\n"
1766 " gl_TessLevelOuter[1] = 1;\n"
1767 " gl_TessLevelOuter[2] = 1;\n"
1768 "}\n";
1769 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(css.str()) << buildOptions;
1770 }
1771
1772 {
1773 std::stringstream css;
1774 css << "#version 460 core\n"
1775 "#extension GL_EXT_tessellation_shader : require\n"
1776 "#extension GL_EXT_ray_query : require\n"
1777 "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1778 "layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
1779 "in gl_PerVertex {\n"
1780 " vec4 gl_Position;\n"
1781 "} gl_in[];\n"
1782 "layout(vertices = 3) out;\n"
1783 "void main (void)\n"
1784 "{\n"
1785 " vec3 origin = vec3(gl_in[gl_InvocationID].gl_Position.x + 0.5, "
1786 "gl_in[gl_InvocationID].gl_Position.y + 0.5, 0.5);\n"
1787 " uvec4 hitValue = uvec4(0,0,0,0);\n"
1788 << rayQueryTest[bottomTestTypeIdx]
1789 << " imageStore(result, ivec3(gl_PrimitiveID, gl_InvocationID, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1790 " imageStore(result, ivec3(gl_PrimitiveID, gl_InvocationID, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1791 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1792 " gl_TessLevelInner[0] = 1;\n"
1793 " gl_TessLevelOuter[0] = 1;\n"
1794 " gl_TessLevelOuter[1] = 1;\n"
1795 " gl_TessLevelOuter[2] = 1;\n"
1796 "}\n";
1797 std::stringstream cssName;
1798 cssName << "tesc_" << rayQueryTestName[bottomTestTypeIdx];
1799
1800 programCollection.glslSources.add(cssName.str())
1801 << glu::TessellationControlSource(css.str()) << buildOptions;
1802 }
1803
1804 {
1805 std::stringstream css;
1806 css << "#version 460 core\n"
1807 "#extension GL_EXT_tessellation_shader : require\n"
1808 "#extension GL_EXT_ray_query : require\n"
1809 "layout(triangles, equal_spacing, ccw) in;\n"
1810 "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1811 "layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
1812 "void main (void)\n"
1813 "{\n"
1814 " for (int i = 0; i < 3; ++i)\n"
1815 " {\n"
1816 " vec3 origin = vec3(gl_in[i].gl_Position.x + 0.5, gl_in[i].gl_Position.y + 0.5, 0.5);\n"
1817 " uvec4 hitValue = uvec4(0,0,0,0);\n"
1818 << rayQueryTest[bottomTestTypeIdx]
1819 << " imageStore(result, ivec3(gl_PrimitiveID, i, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1820 " imageStore(result, ivec3(gl_PrimitiveID, i, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1821 " }\n"
1822 " gl_Position = gl_in[0].gl_Position;\n"
1823 "}\n";
1824 std::stringstream cssName;
1825 cssName << "tese_" << rayQueryTestName[bottomTestTypeIdx];
1826
1827 programCollection.glslSources.add(cssName.str())
1828 << glu::TessellationEvaluationSource(css.str()) << buildOptions;
1829 }
1830
1831 {
1832 std::stringstream css;
1833 css << "#version 460 core\n"
1834 "#extension GL_EXT_tessellation_shader : require\n"
1835 "layout(triangles, equal_spacing, ccw) in;\n"
1836 "void main (void)\n"
1837 "{\n"
1838 " gl_Position = gl_in[0].gl_Position;\n"
1839 "}\n";
1840
1841 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(css.str()) << buildOptions;
1842 }
1843
1844 {
1845 std::stringstream css;
1846 css << "#version 460 core\n"
1847 "#extension GL_EXT_ray_query : require\n"
1848 "layout(triangles) in;\n"
1849 "layout (triangle_strip, max_vertices = 4) out;\n"
1850 "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1851 "layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
1852 "\n"
1853 "in gl_PerVertex {\n"
1854 " vec4 gl_Position;\n"
1855 "} gl_in[];\n"
1856 "layout(location = 0) in int vertexIndex[];\n"
1857 "out gl_PerVertex {\n"
1858 " vec4 gl_Position;\n"
1859 "};\n"
1860 "void main (void)\n"
1861 "{\n"
1862 " // geometry shader may reorder the vertices, keeping only the winding of the triangles.\n"
1863 " // To iterate from the 'first vertex' of the triangle we need to find it first by looking for\n"
1864 " // smallest vertex index value.\n"
1865 " int minVertexIndex = 10000;"
1866 " int firstVertex;"
1867 " for (int i = 0; i < gl_in.length(); ++i)\n"
1868 " {\n"
1869 " if (minVertexIndex > vertexIndex[i])\n"
1870 " {\n"
1871 " minVertexIndex = vertexIndex[i];\n"
1872 " firstVertex = i;\n"
1873 " }\n"
1874 " }\n"
1875 " for (int j = 0; j < gl_in.length(); ++j)\n"
1876 " {\n"
1877 " // iterate starting at firstVertex, possibly wrapping around, so the triangle is\n"
1878 " // always iterated starting from the smallest vertex index, as found above.\n"
1879 " int i = (firstVertex + j) % gl_in.length();\n"
1880 " vec3 origin = vec3(gl_in[i].gl_Position.x + 0.5, gl_in[i].gl_Position.y + 0.5, 0.5);\n"
1881 " uvec4 hitValue = uvec4(0,0,0,0);\n"
1882 << rayQueryTest[bottomTestTypeIdx]
1883 << " imageStore(result, ivec3(gl_PrimitiveIDIn, j, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1884 " imageStore(result, ivec3(gl_PrimitiveIDIn, j, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1885 " gl_Position = gl_in[i].gl_Position;\n"
1886 " EmitVertex();\n"
1887 " }\n"
1888 " EndPrimitive();\n"
1889 "}\n";
1890 std::stringstream cssName;
1891 cssName << "geom_" << rayQueryTestName[bottomTestTypeIdx];
1892
1893 programCollection.glslSources.add(cssName.str()) << glu::GeometrySource(css.str()) << buildOptions;
1894 }
1895
1896 {
1897 std::stringstream css;
1898 css << "#version 460 core\n"
1899 "#extension GL_EXT_ray_query : require\n"
1900 "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1901 "layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
1902 "void main()\n"
1903 "{\n"
1904 " vec3 origin = vec3(gl_FragCoord.x, gl_FragCoord.y, 0.5);\n"
1905 " uvec4 hitValue = uvec4(0,0,0,0);\n"
1906 << rayQueryTest[bottomTestTypeIdx]
1907 << " imageStore(result, ivec3(gl_FragCoord.xy-vec2(0.5,0.5), 0), uvec4(hitValue.x, 0, 0, 0));\n"
1908 " imageStore(result, ivec3(gl_FragCoord.xy-vec2(0.5,0.5), 1), uvec4(hitValue.y, 0, 0, 0));\n"
1909 "}\n";
1910 std::stringstream cssName;
1911 cssName << "frag_" << rayQueryTestName[bottomTestTypeIdx];
1912
1913 programCollection.glslSources.add(cssName.str()) << glu::FragmentSource(css.str()) << buildOptions;
1914 }
1915 }
1916 else if (m_data.shaderSourcePipeline == SSP_COMPUTE_PIPELINE)
1917 {
1918 {
1919 std::stringstream css;
1920 css << "#version 460 core\n"
1921 "#extension GL_EXT_ray_query : require\n"
1922 "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1923 "layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
1924 "void main()\n"
1925 "{\n"
1926 " vec3 origin = vec3(float(gl_GlobalInvocationID.x) + 0.5, float(gl_GlobalInvocationID.y) + "
1927 "0.5, 0.5);\n"
1928 " uvec4 hitValue = uvec4(0,0,0,0);\n"
1929 << rayQueryTest[bottomTestTypeIdx]
1930 << " imageStore(result, ivec3(gl_GlobalInvocationID.xy, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1931 " imageStore(result, ivec3(gl_GlobalInvocationID.xy, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1932 "}\n";
1933 std::stringstream cssName;
1934 cssName << "comp_" << rayQueryTestName[bottomTestTypeIdx];
1935
1936 programCollection.glslSources.add(cssName.str()) << glu::ComputeSource(css.str()) << buildOptions;
1937 }
1938 }
1939 else if (m_data.shaderSourcePipeline == SSP_RAY_TRACING_PIPELINE)
1940 {
1941 {
1942 std::stringstream css;
1943 css << "#version 460 core\n"
1944 "#extension GL_EXT_ray_tracing : require\n"
1945 "layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
1946 "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1947 "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
1948 "void main()\n"
1949 "{\n"
1950 " float tmin = 0.0;\n"
1951 " float tmax = 1.0;\n"
1952 " vec3 origin = vec3(float(gl_LaunchIDEXT.x) + 0.5, float(gl_LaunchIDEXT.y) + 0.5, 0.5);\n"
1953 " vec3 direct = vec3(0.0, 0.0, -1.0);\n"
1954 " hitValue = uvec4(0,0,0,0);\n"
1955 " traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
1956 " imageStore(result, ivec3(gl_LaunchIDEXT.xy, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1957 " imageStore(result, ivec3(gl_LaunchIDEXT.xy, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1958 "}\n";
1959 programCollection.glslSources.add("rgen")
1960 << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1961 }
1962
1963 {
1964 std::stringstream css;
1965 css << "#version 460 core\n"
1966 "#extension GL_EXT_ray_tracing : require\n"
1967 "#extension GL_EXT_ray_query : require\n"
1968 "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1969 "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
1970 "layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
1971 "void main()\n"
1972 "{\n"
1973 " vec3 origin = vec3(float(gl_LaunchIDEXT.x) + 0.5, float(gl_LaunchIDEXT.y) + 0.5, 0.5);\n"
1974 " uvec4 hitValue = uvec4(0,0,0,0);\n"
1975 << rayQueryTest[bottomTestTypeIdx]
1976 << " imageStore(result, ivec3(gl_LaunchIDEXT.xy, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1977 " imageStore(result, ivec3(gl_LaunchIDEXT.xy, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1978 "}\n";
1979 std::stringstream cssName;
1980 cssName << "rgen_" << rayQueryTestName[bottomTestTypeIdx];
1981
1982 programCollection.glslSources.add(cssName.str())
1983 << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1984 }
1985
1986 {
1987 std::stringstream css;
1988 css << "#version 460 core\n"
1989 "#extension GL_EXT_ray_tracing : require\n"
1990 "struct CallValue\n{\n"
1991 " vec3 origin;\n"
1992 " uvec4 hitValue;\n"
1993 "};\n"
1994 "layout(location = 0) callableDataEXT CallValue param;\n"
1995 "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1996 "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
1997 "void main()\n"
1998 "{\n"
1999 " param.origin = vec3(float(gl_LaunchIDEXT.x) + 0.5, float(gl_LaunchIDEXT.y) + 0.5, 0.5);\n"
2000 " param.hitValue = uvec4(0, 0, 0, 0);\n"
2001 " executeCallableEXT(0, 0);\n"
2002 " imageStore(result, ivec3(gl_LaunchIDEXT.xy, 0), uvec4(param.hitValue.x, 0, 0, 0));\n"
2003 " imageStore(result, ivec3(gl_LaunchIDEXT.xy, 1), uvec4(param.hitValue.y, 0, 0, 0));\n"
2004 "}\n";
2005 programCollection.glslSources.add("rgen_call")
2006 << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
2007 }
2008
2009 {
2010 std::stringstream css;
2011 css << "#version 460 core\n"
2012 "#extension GL_EXT_ray_tracing : require\n"
2013 "hitAttributeEXT uvec4 hitValue;\n"
2014 "void main()\n"
2015 "{\n"
2016 " reportIntersectionEXT(0.5f, 0);\n"
2017 "}\n";
2018
2019 programCollection.glslSources.add("isect")
2020 << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
2021 }
2022
2023 {
2024 std::stringstream css;
2025 css << "#version 460 core\n"
2026 "#extension GL_EXT_ray_tracing : require\n"
2027 "#extension GL_EXT_ray_query : require\n"
2028 "hitAttributeEXT uvec4 hitValue;\n"
2029 "layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
2030 "void main()\n"
2031 "{\n"
2032 " vec3 origin = gl_WorldRayOriginEXT;\n"
2033 " hitValue = uvec4(0,0,0,0);\n"
2034 << rayQueryTest[bottomTestTypeIdx]
2035 << " reportIntersectionEXT(0.5f, 0);\n"
2036 "}\n";
2037 std::stringstream cssName;
2038 cssName << "isect_" << rayQueryTestName[bottomTestTypeIdx];
2039
2040 programCollection.glslSources.add(cssName.str())
2041 << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
2042 }
2043
2044 {
2045 std::stringstream css;
2046 css << "#version 460 core\n"
2047 "#extension GL_EXT_ray_tracing : require\n"
2048 "#extension GL_EXT_ray_query : require\n"
2049 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
2050 "layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
2051 "void main()\n"
2052 "{\n"
2053 " vec3 origin = gl_WorldRayOriginEXT;\n"
2054 << rayQueryTest[bottomTestTypeIdx] << "}\n";
2055 std::stringstream cssName;
2056 cssName << "ahit_" << rayQueryTestName[bottomTestTypeIdx];
2057
2058 programCollection.glslSources.add(cssName.str())
2059 << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
2060 }
2061
2062 {
2063 std::stringstream css;
2064 css << "#version 460 core\n"
2065 "#extension GL_EXT_ray_tracing : require\n"
2066 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
2067 "void main()\n"
2068 "{\n"
2069 " hitValue.y = 3;\n"
2070 "}\n";
2071
2072 programCollection.glslSources.add("chit")
2073 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
2074 }
2075
2076 {
2077 std::stringstream css;
2078 css << "#version 460 core\n"
2079 "#extension GL_EXT_ray_tracing : require\n"
2080 "#extension GL_EXT_ray_query : require\n"
2081 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
2082 "layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
2083 "void main()\n"
2084 "{\n"
2085 " vec3 origin = gl_WorldRayOriginEXT;\n"
2086 << rayQueryTest[bottomTestTypeIdx] << "}\n";
2087 std::stringstream cssName;
2088 cssName << "chit_" << rayQueryTestName[bottomTestTypeIdx];
2089
2090 programCollection.glslSources.add(cssName.str())
2091 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
2092 }
2093
2094 {
2095 std::stringstream css;
2096 css << "#version 460 core\n"
2097 "#extension GL_EXT_ray_tracing : require\n"
2098 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
2099 "hitAttributeEXT uvec4 hitAttrib;\n"
2100 "void main()\n"
2101 "{\n"
2102 " hitValue = hitAttrib;\n"
2103 "}\n";
2104
2105 programCollection.glslSources.add("chit_isect")
2106 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
2107 }
2108
2109 {
2110 std::stringstream css;
2111 css << "#version 460 core\n"
2112 "#extension GL_EXT_ray_tracing : require\n"
2113 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
2114 "void main()\n"
2115 "{\n"
2116 " hitValue.x = 4;\n"
2117 "}\n";
2118
2119 programCollection.glslSources.add("miss")
2120 << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
2121 }
2122
2123 {
2124 std::stringstream css;
2125 css << "#version 460 core\n"
2126 "#extension GL_EXT_ray_tracing : require\n"
2127 "#extension GL_EXT_ray_query : require\n"
2128 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
2129 "layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
2130 "void main()\n"
2131 "{\n"
2132 " vec3 origin = gl_WorldRayOriginEXT;\n"
2133 << rayQueryTest[bottomTestTypeIdx] << "}\n";
2134 std::stringstream cssName;
2135 cssName << "miss_" << rayQueryTestName[bottomTestTypeIdx];
2136
2137 programCollection.glslSources.add(cssName.str())
2138 << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
2139 }
2140
2141 {
2142 std::stringstream css;
2143 css << "#version 460 core\n"
2144 "#extension GL_EXT_ray_tracing : require\n"
2145 "#extension GL_EXT_ray_query : require\n"
2146 "struct CallValue\n{\n"
2147 " vec3 origin;\n"
2148 " uvec4 hitValue;\n"
2149 "};\n"
2150 "layout(location = 0) callableDataInEXT CallValue result;\n"
2151 "layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
2152 "void main()\n"
2153 "{\n"
2154 " vec3 origin = result.origin;\n"
2155 " uvec4 hitValue = uvec4(0,0,0,0);\n"
2156 << rayQueryTest[bottomTestTypeIdx]
2157 << " result.hitValue = hitValue;\n"
2158 "}\n";
2159 std::stringstream cssName;
2160 cssName << "call_" << rayQueryTestName[bottomTestTypeIdx];
2161
2162 programCollection.glslSources.add(cssName.str())
2163 << glu::CallableSource(updateRayTracingGLSL(css.str())) << buildOptions;
2164 }
2165 }
2166 }
2167
createInstance(Context & context) const2168 TestInstance *RayQueryASBasicTestCase::createInstance(Context &context) const
2169 {
2170 return new RayQueryASBasicTestInstance(context, m_data);
2171 }
2172
RayQueryASFuncArgTestCase(tcu::TestContext & context,const char * name,const TestParams & data)2173 RayQueryASFuncArgTestCase::RayQueryASFuncArgTestCase(tcu::TestContext &context, const char *name,
2174 const TestParams &data)
2175 : RayQueryASBasicTestCase(context, name, data)
2176 {
2177 }
2178
initPrograms(SourceCollections & programCollection) const2179 void RayQueryASFuncArgTestCase::initPrograms(SourceCollections &programCollection) const
2180 {
2181 const vk::SpirVAsmBuildOptions spvBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
2182
2183 DE_ASSERT(m_data.shaderSourcePipeline == SSP_COMPUTE_PIPELINE);
2184 DE_ASSERT(m_data.bottomTestType == BottomTestType::TRIANGLES);
2185
2186 // The SPIR-V assembly shader below is based on the following GLSL code.
2187 // In it, rayQueryInitializeBottomWrapper has been modified to take a
2188 // bare AS as the second argument, instead of a pointer.
2189 //
2190 // #version 460 core
2191 // #extension GL_EXT_ray_query : require
2192 // layout(r32ui, set = 0, binding = 0) uniform uimage3D result;
2193 // layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;
2194 //
2195 // void rayQueryInitializeBottomWrapper(rayQueryEXT rayQuery,
2196 // accelerationStructureEXT topLevel,
2197 // uint rayFlags, uint cullMask, vec3 origin,
2198 // float tMin, vec3 direction, float tMax)
2199 // {
2200 // rayQueryInitializeEXT(rayQuery, topLevel, rayFlags, cullMask, origin, tMin, direction, tMax);
2201 // }
2202 //
2203 // void rayQueryInitializeTopWrapper(rayQueryEXT rayQuery,
2204 // accelerationStructureEXT topLevel,
2205 // uint rayFlags, uint cullMask, vec3 origin,
2206 // float tMin, vec3 direction, float tMax)
2207 // {
2208 // rayQueryInitializeBottomWrapper(rayQuery, topLevel, rayFlags, cullMask, origin, tMin, direction, tMax);
2209 // }
2210 //
2211 // void main()
2212 // {
2213 // vec3 origin = vec3(float(gl_GlobalInvocationID.x) + 0.5, float(gl_GlobalInvocationID.y) + 0.5, 0.5);
2214 // uvec4 hitValue = uvec4(0,0,0,0);
2215 // float tmin = 0.0;
2216 // float tmax = 1.0;
2217 // vec3 direct = vec3(0.0, 0.0, -1.0);
2218 // rayQueryEXT rq;
2219 // rayQueryInitializeTopWrapper(rq, rqTopLevelAS, 0, 0xFF, origin, tmin, direct, tmax);
2220 // if(rayQueryProceedEXT(rq))
2221 // {
2222 // if (rayQueryGetIntersectionTypeEXT(rq, false)==gl_RayQueryCandidateIntersectionTriangleEXT)
2223 // {
2224 // hitValue.y = 1;
2225 // hitValue.x = 1;
2226 // }
2227 // }
2228 // imageStore(result, ivec3(gl_GlobalInvocationID.xy, 0), uvec4(hitValue.x, 0, 0, 0));
2229 // imageStore(result, ivec3(gl_GlobalInvocationID.xy, 1), uvec4(hitValue.y, 0, 0, 0));
2230 // }
2231
2232 std::stringstream css;
2233 css << "; SPIR-V\n"
2234 << "; Version: 1.4\n"
2235 << "; Generator: Khronos Glslang Reference Front End; 10\n"
2236 << "; Bound: 139\n"
2237 << "; Schema: 0\n"
2238 << "OpCapability Shader\n"
2239 << "OpCapability RayQueryKHR\n"
2240 << "OpExtension \"SPV_KHR_ray_query\"\n"
2241 << "%1 = OpExtInstImport \"GLSL.std.450\"\n"
2242 << "OpMemoryModel Logical GLSL450\n"
2243 << "OpEntryPoint GLCompute %4 \"main\" %60 %86 %114\n"
2244 << "OpExecutionMode %4 LocalSize 1 1 1\n"
2245 << "OpDecorate %60 BuiltIn GlobalInvocationId\n"
2246 << "OpDecorate %86 DescriptorSet 0\n"
2247 << "OpDecorate %86 Binding 1\n"
2248 << "OpDecorate %114 DescriptorSet 0\n"
2249 << "OpDecorate %114 Binding 0\n"
2250 << "%2 = OpTypeVoid\n"
2251 << "%3 = OpTypeFunction %2\n"
2252
2253 // Bare query type
2254 << "%6 = OpTypeRayQueryKHR\n"
2255
2256 // Pointer to query.
2257 << "%7 = OpTypePointer Function %6\n"
2258
2259 // Bare AS type.
2260 << "%8 = OpTypeAccelerationStructureKHR\n"
2261
2262 // Pointer to AS.
2263 << "%9 = OpTypePointer UniformConstant %8\n"
2264
2265 << "%10 = OpTypeInt 32 0\n"
2266 << "%11 = OpTypePointer Function %10\n"
2267 << "%12 = OpTypeFloat 32\n"
2268 << "%13 = OpTypeVector %12 3\n"
2269 << "%14 = OpTypePointer Function %13\n"
2270 << "%15 = OpTypePointer Function %12\n"
2271
2272 // This is the function type for rayQueryInitializeTopWrapper and the old rayQueryInitializeBottomWrapper.
2273 << "%16 = OpTypeFunction %2 %7 %9 %11 %11 %14 %15 %14 %15\n"
2274
2275 // This is the new function type for the modified rayQueryInitializeBottomWrapper that uses a bare AS.
2276 //<< "%16b = OpTypeFunction %2 %6 %8 %11 %11 %14 %15 %14 %15\n"
2277 << "%16b = OpTypeFunction %2 %7 %8 %11 %11 %14 %15 %14 %15\n"
2278
2279 << "%58 = OpTypeVector %10 3\n"
2280 << "%59 = OpTypePointer Input %58\n"
2281 << "%60 = OpVariable %59 Input\n"
2282 << "%61 = OpConstant %10 0\n"
2283 << "%62 = OpTypePointer Input %10\n"
2284 << "%66 = OpConstant %12 0.5\n"
2285 << "%68 = OpConstant %10 1\n"
2286 << "%74 = OpTypeVector %10 4\n"
2287 << "%75 = OpTypePointer Function %74\n"
2288 << "%77 = OpConstantComposite %74 %61 %61 %61 %61\n"
2289 << "%79 = OpConstant %12 0\n"
2290 << "%81 = OpConstant %12 1\n"
2291 << "%83 = OpConstant %12 -1\n"
2292 << "%84 = OpConstantComposite %13 %79 %79 %83\n"
2293 << "%86 = OpVariable %9 UniformConstant\n"
2294 << "%87 = OpConstant %10 255\n"
2295 << "%99 = OpTypeBool\n"
2296 << "%103 = OpConstantFalse %99\n"
2297 << "%104 = OpTypeInt 32 1\n"
2298 << "%105 = OpConstant %104 0\n"
2299 << "%112 = OpTypeImage %10 3D 0 0 0 2 R32ui\n"
2300 << "%113 = OpTypePointer UniformConstant %112\n"
2301 << "%114 = OpVariable %113 UniformConstant\n"
2302 << "%116 = OpTypeVector %10 2\n"
2303 << "%119 = OpTypeVector %104 2\n"
2304 << "%121 = OpTypeVector %104 3\n"
2305 << "%132 = OpConstant %104 1\n"
2306
2307 // This is main().
2308 << "%4 = OpFunction %2 None %3\n"
2309 << "%5 = OpLabel\n"
2310 << "%57 = OpVariable %14 Function\n"
2311 << "%76 = OpVariable %75 Function\n"
2312 << "%78 = OpVariable %15 Function\n"
2313 << "%80 = OpVariable %15 Function\n"
2314 << "%82 = OpVariable %14 Function\n"
2315 << "%85 = OpVariable %7 Function\n"
2316 << "%88 = OpVariable %11 Function\n"
2317 << "%89 = OpVariable %11 Function\n"
2318 << "%90 = OpVariable %14 Function\n"
2319 << "%92 = OpVariable %15 Function\n"
2320 << "%94 = OpVariable %14 Function\n"
2321 << "%96 = OpVariable %15 Function\n"
2322 << "%63 = OpAccessChain %62 %60 %61\n"
2323 << "%64 = OpLoad %10 %63\n"
2324 << "%65 = OpConvertUToF %12 %64\n"
2325 << "%67 = OpFAdd %12 %65 %66\n"
2326 << "%69 = OpAccessChain %62 %60 %68\n"
2327 << "%70 = OpLoad %10 %69\n"
2328 << "%71 = OpConvertUToF %12 %70\n"
2329 << "%72 = OpFAdd %12 %71 %66\n"
2330 << "%73 = OpCompositeConstruct %13 %67 %72 %66\n"
2331 << "OpStore %57 %73\n"
2332 << "OpStore %76 %77\n"
2333 << "OpStore %78 %79\n"
2334 << "OpStore %80 %81\n"
2335 << "OpStore %82 %84\n"
2336 << "OpStore %88 %61\n"
2337 << "OpStore %89 %87\n"
2338 << "%91 = OpLoad %13 %57\n"
2339 << "OpStore %90 %91\n"
2340 << "%93 = OpLoad %12 %78\n"
2341 << "OpStore %92 %93\n"
2342 << "%95 = OpLoad %13 %82\n"
2343 << "OpStore %94 %95\n"
2344 << "%97 = OpLoad %12 %80\n"
2345 << "OpStore %96 %97\n"
2346 << "%98 = OpFunctionCall %2 %35 %85 %86 %88 %89 %90 %92 %94 %96\n"
2347 << "%100 = OpRayQueryProceedKHR %99 %85\n"
2348 << "OpSelectionMerge %102 None\n"
2349 << "OpBranchConditional %100 %101 %102\n"
2350 << "%101 = OpLabel\n"
2351 << "%106 = OpRayQueryGetIntersectionTypeKHR %10 %85 %105\n"
2352 << "%107 = OpIEqual %99 %106 %61\n"
2353 << "OpSelectionMerge %109 None\n"
2354 << "OpBranchConditional %107 %108 %109\n"
2355 << "%108 = OpLabel\n"
2356 << "%110 = OpAccessChain %11 %76 %68\n"
2357 << "OpStore %110 %68\n"
2358 << "%111 = OpAccessChain %11 %76 %61\n"
2359 << "OpStore %111 %68\n"
2360 << "OpBranch %109\n"
2361 << "%109 = OpLabel\n"
2362 << "OpBranch %102\n"
2363 << "%102 = OpLabel\n"
2364 << "%115 = OpLoad %112 %114\n"
2365 << "%117 = OpLoad %58 %60\n"
2366 << "%118 = OpVectorShuffle %116 %117 %117 0 1\n"
2367 << "%120 = OpBitcast %119 %118\n"
2368 << "%122 = OpCompositeExtract %104 %120 0\n"
2369 << "%123 = OpCompositeExtract %104 %120 1\n"
2370 << "%124 = OpCompositeConstruct %121 %122 %123 %105\n"
2371 << "%125 = OpAccessChain %11 %76 %61\n"
2372 << "%126 = OpLoad %10 %125\n"
2373 << "%127 = OpCompositeConstruct %74 %126 %61 %61 %61\n"
2374 << "OpImageWrite %115 %124 %127 ZeroExtend\n"
2375 << "%128 = OpLoad %112 %114\n"
2376 << "%129 = OpLoad %58 %60\n"
2377 << "%130 = OpVectorShuffle %116 %129 %129 0 1\n"
2378 << "%131 = OpBitcast %119 %130\n"
2379 << "%133 = OpCompositeExtract %104 %131 0\n"
2380 << "%134 = OpCompositeExtract %104 %131 1\n"
2381 << "%135 = OpCompositeConstruct %121 %133 %134 %132\n"
2382 << "%136 = OpAccessChain %11 %76 %68\n"
2383 << "%137 = OpLoad %10 %136\n"
2384 << "%138 = OpCompositeConstruct %74 %137 %61 %61 %61\n"
2385 << "OpImageWrite %128 %135 %138 ZeroExtend\n"
2386 << "OpReturn\n"
2387 << "OpFunctionEnd\n"
2388
2389 // This is rayQueryInitializeBottomWrapper, calling OpRayQueryInitializeKHR.
2390 // We have modified the function type so it takes bare arguments.
2391 //%25 = OpFunction %2 None %16
2392 << "%25 = OpFunction %2 None %16b\n"
2393
2394 // These is the modified parameter.
2395 << "%17 = OpFunctionParameter %7\n"
2396 //<< "%17 = OpFunctionParameter %6\n"
2397 //%18 = OpFunctionParameter %9
2398 << "%18 = OpFunctionParameter %8\n"
2399
2400 << "%19 = OpFunctionParameter %11\n"
2401 << "%20 = OpFunctionParameter %11\n"
2402 << "%21 = OpFunctionParameter %14\n"
2403 << "%22 = OpFunctionParameter %15\n"
2404 << "%23 = OpFunctionParameter %14\n"
2405 << "%24 = OpFunctionParameter %15\n"
2406 << "%26 = OpLabel\n"
2407
2408 // We no longer need to load this parameter.
2409 //%37 = OpLoad %8 %18
2410
2411 << "%38 = OpLoad %10 %19\n"
2412 << "%39 = OpLoad %10 %20\n"
2413 << "%40 = OpLoad %13 %21\n"
2414 << "%41 = OpLoad %12 %22\n"
2415 << "%42 = OpLoad %13 %23\n"
2416 << "%43 = OpLoad %12 %24\n"
2417
2418 // We call OpRayQueryInitializeKHR with bare arguments.
2419 // Note: some experimental lines to pass a bare rayQuery as the first argument have been commented out.
2420 //OpRayQueryInitializeKHR %17 %37 %38 %39 %40 %41 %42 %43
2421 << "OpRayQueryInitializeKHR %17 %18 %38 %39 %40 %41 %42 %43\n"
2422
2423 << "OpReturn\n"
2424 << "OpFunctionEnd\n"
2425
2426 // This is rayQueryInitializeTopWrapper, calling rayQueryInitializeBottomWrapper.
2427 << "%35 = OpFunction %2 None %16\n"
2428 << "%27 = OpFunctionParameter %7\n"
2429 << "%28 = OpFunctionParameter %9\n"
2430 << "%29 = OpFunctionParameter %11\n"
2431 << "%30 = OpFunctionParameter %11\n"
2432 << "%31 = OpFunctionParameter %14\n"
2433 << "%32 = OpFunctionParameter %15\n"
2434 << "%33 = OpFunctionParameter %14\n"
2435 << "%34 = OpFunctionParameter %15\n"
2436 << "%36 = OpLabel\n"
2437 << "%44 = OpVariable %11 Function\n"
2438 << "%46 = OpVariable %11 Function\n"
2439 << "%48 = OpVariable %14 Function\n"
2440 << "%50 = OpVariable %15 Function\n"
2441 << "%52 = OpVariable %14 Function\n"
2442 << "%54 = OpVariable %15 Function\n"
2443
2444 // We need to load the second argument.
2445 //<< "%27b = OpLoad %6 %27\n"
2446 << "%28b = OpLoad %8 %28\n"
2447
2448 << "%45 = OpLoad %10 %29\n"
2449 << "OpStore %44 %45\n"
2450 << "%47 = OpLoad %10 %30\n"
2451 << "OpStore %46 %47\n"
2452 << "%49 = OpLoad %13 %31\n"
2453 << "OpStore %48 %49\n"
2454 << "%51 = OpLoad %12 %32\n"
2455 << "OpStore %50 %51\n"
2456 << "%53 = OpLoad %13 %33\n"
2457 << "OpStore %52 %53\n"
2458 << "%55 = OpLoad %12 %34\n"
2459 << "OpStore %54 %55\n"
2460
2461 // We call rayQueryInitializeBottomWrapper with the loaded argument.
2462 //%56 = OpFunctionCall %2 %25 %27 %28 %44 %46 %48 %50 %52 %54
2463 //<< "%56 = OpFunctionCall %2 %25 %27b %28b %44 %46 %48 %50 %52 %54\n"
2464 << "%56 = OpFunctionCall %2 %25 %27 %28b %44 %46 %48 %50 %52 %54\n"
2465
2466 << "OpReturn\n"
2467 << "OpFunctionEnd\n";
2468
2469 programCollection.spirvAsmSources.add("comp_as_triangle") << spvBuildOptions << css.str();
2470 }
2471
RayQueryASBasicTestInstance(Context & context,const TestParams & data)2472 RayQueryASBasicTestInstance::RayQueryASBasicTestInstance(Context &context, const TestParams &data)
2473 : vkt::TestInstance(context)
2474 , m_data(data)
2475 {
2476 }
2477
~RayQueryASBasicTestInstance(void)2478 RayQueryASBasicTestInstance::~RayQueryASBasicTestInstance(void)
2479 {
2480 }
2481
runTest(TestConfiguration * testConfiguration,SceneBuilder * sceneBuilder,const uint32_t workerThreadsCount)2482 de::MovePtr<BufferWithMemory> RayQueryASBasicTestInstance::runTest(TestConfiguration *testConfiguration,
2483 SceneBuilder *sceneBuilder,
2484 const uint32_t workerThreadsCount)
2485 {
2486 testConfiguration->initConfiguration(m_context, m_data);
2487
2488 const DeviceInterface &vkd = m_context.getDeviceInterface();
2489 const VkDevice device = m_context.getDevice();
2490 const VkQueue queue = m_context.getUniversalQueue();
2491 Allocator &allocator = m_context.getDefaultAllocator();
2492 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2493
2494 const bool htCopy = (workerThreadsCount != 0) && (m_data.operationType == OP_COPY);
2495 const bool htSerialize = (workerThreadsCount != 0) && (m_data.operationType == OP_SERIALIZE);
2496
2497 const VkFormat imageFormat = testConfiguration->getResultImageFormat();
2498 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_data.width, m_data.height, 2, imageFormat);
2499 const VkImageSubresourceRange imageSubresourceRange =
2500 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2501 const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
2502 new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
2503 const Move<VkImageView> imageView =
2504 makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, imageFormat, imageSubresourceRange);
2505
2506 const VkBufferCreateInfo resultBufferCreateInfo =
2507 makeBufferCreateInfo(m_data.width * m_data.height * 2 * testConfiguration->getResultImageFormatSize(),
2508 VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2509 const VkImageSubresourceLayers resultBufferImageSubresourceLayers =
2510 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2511 const VkBufferImageCopy resultBufferImageRegion =
2512 makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 2), resultBufferImageSubresourceLayers);
2513 de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(
2514 new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
2515
2516 const VkDescriptorImageInfo resultImageInfo = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
2517
2518 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
2519 const Move<VkCommandBuffer> cmdBuffer =
2520 allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2521
2522 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures;
2523 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
2524 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructureCopies;
2525 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructureCopy;
2526 std::vector<de::SharedPtr<SerialStorage>> bottomSerialized;
2527 std::vector<de::SharedPtr<SerialStorage>> topSerialized;
2528 std::vector<VkDeviceSize> accelerationCompactedSizes;
2529 std::vector<VkDeviceSize> accelerationSerialSizes;
2530 Move<VkQueryPool> m_queryPoolCompact;
2531 Move<VkQueryPool> m_queryPoolSerial;
2532
2533 beginCommandBuffer(vkd, *cmdBuffer, 0u);
2534 {
2535 const VkImageMemoryBarrier preImageBarrier =
2536 makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2537 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
2538 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
2539 VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
2540
2541 const VkClearValue clearValue = testConfiguration->getClearValue();
2542 vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
2543 &imageSubresourceRange);
2544
2545 const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
2546 VK_ACCESS_TRANSFER_WRITE_BIT,
2547 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
2548 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
2549 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
2550 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
2551
2552 // build bottom level acceleration structures and their copies ( only when we are testing copying bottom level acceleration structures )
2553 bool bottomCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
2554 bool bottomSerial = m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
2555 const bool buildWithoutGeom = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM);
2556 const bool bottomNoPrimitives = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM);
2557 const bool topNoPrimitives = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP);
2558 const bool inactiveInstances = (m_data.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_INSTANCES);
2559 bottomLevelAccelerationStructures = sceneBuilder->initBottomAccelerationStructures(m_context, m_data);
2560 VkBuildAccelerationStructureFlagsKHR allowCompactionFlag =
2561 VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
2562 VkBuildAccelerationStructureFlagsKHR emptyCompactionFlag = VkBuildAccelerationStructureFlagsKHR(0);
2563 VkBuildAccelerationStructureFlagsKHR bottomCompactFlags =
2564 (bottomCompact ? allowCompactionFlag : emptyCompactionFlag);
2565 VkBuildAccelerationStructureFlagsKHR bottomBuildFlags = m_data.buildFlags | bottomCompactFlags;
2566 std::vector<VkAccelerationStructureKHR> accelerationStructureHandles;
2567 std::vector<VkDeviceSize> bottomBlasCompactSize;
2568 std::vector<VkDeviceSize> bottomBlasSerialSize;
2569
2570 for (auto &blas : bottomLevelAccelerationStructures)
2571 {
2572 blas->setBuildType(m_data.buildType);
2573 blas->setBuildFlags(bottomBuildFlags);
2574 blas->setUseArrayOfPointers(m_data.bottomUsesAOP);
2575 blas->setCreateGeneric(m_data.bottomGeneric);
2576 blas->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
2577 blas->setBuildWithoutGeometries(buildWithoutGeom);
2578 blas->setBuildWithoutPrimitives(bottomNoPrimitives);
2579 blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
2580 accelerationStructureHandles.push_back(*(blas->getPtr()));
2581 }
2582
2583 if (m_data.operationType == OP_COMPACT)
2584 {
2585 uint32_t queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ?
2586 uint32_t(bottomLevelAccelerationStructures.size()) :
2587 1u;
2588 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2589 m_queryPoolCompact =
2590 makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount);
2591 if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
2592 queryAccelerationStructureSize(
2593 vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolCompact.get(),
2594 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, bottomBlasCompactSize);
2595 }
2596 if (m_data.operationType == OP_SERIALIZE)
2597 {
2598 uint32_t queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ?
2599 uint32_t(bottomLevelAccelerationStructures.size()) :
2600 1u;
2601 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2602 m_queryPoolSerial =
2603 makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
2604 if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
2605 queryAccelerationStructureSize(
2606 vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolSerial.get(),
2607 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, bottomBlasSerialSize);
2608 }
2609
2610 // if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU
2611 if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (bottomCompact || bottomSerial))
2612 {
2613 endCommandBuffer(vkd, *cmdBuffer);
2614
2615 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2616
2617 if (bottomCompact)
2618 VK_CHECK(vkd.getQueryPoolResults(
2619 device, *m_queryPoolCompact, 0u, uint32_t(bottomBlasCompactSize.size()),
2620 sizeof(VkDeviceSize) * bottomBlasCompactSize.size(), bottomBlasCompactSize.data(),
2621 sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
2622 if (bottomSerial)
2623 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, uint32_t(bottomBlasSerialSize.size()),
2624 sizeof(VkDeviceSize) * bottomBlasSerialSize.size(),
2625 bottomBlasSerialSize.data(), sizeof(VkDeviceSize),
2626 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
2627
2628 vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2629 beginCommandBuffer(vkd, *cmdBuffer, 0u);
2630 }
2631
2632 auto bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructures;
2633 if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_BOTTOM_ACCELERATION)
2634 {
2635 switch (m_data.operationType)
2636 {
2637 case OP_COPY:
2638 {
2639 for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
2640 {
2641 de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
2642 asCopy->setDeferredOperation(htCopy, workerThreadsCount);
2643 asCopy->setBuildType(m_data.buildType);
2644 asCopy->setBuildFlags(m_data.buildFlags);
2645 asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
2646 asCopy->setCreateGeneric(m_data.bottomGeneric);
2647 asCopy->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
2648 asCopy->setBuildWithoutGeometries(buildWithoutGeom);
2649 asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
2650 asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator,
2651 bottomLevelAccelerationStructures[i].get(), 0u, 0u);
2652 bottomLevelAccelerationStructureCopies.push_back(
2653 de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
2654 }
2655 break;
2656 }
2657 case OP_COMPACT:
2658 {
2659 for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
2660 {
2661 de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
2662 asCopy->setBuildType(m_data.buildType);
2663 asCopy->setBuildFlags(m_data.buildFlags);
2664 asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
2665 asCopy->setCreateGeneric(m_data.bottomGeneric);
2666 asCopy->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
2667 asCopy->setBuildWithoutGeometries(buildWithoutGeom);
2668 asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
2669 asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator,
2670 bottomLevelAccelerationStructures[i].get(), bottomBlasCompactSize[i], 0u);
2671 bottomLevelAccelerationStructureCopies.push_back(
2672 de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
2673 }
2674 break;
2675 }
2676 case OP_SERIALIZE:
2677 {
2678 for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
2679 {
2680 de::SharedPtr<SerialStorage> storage(
2681 new SerialStorage(vkd, device, allocator, m_data.buildType, bottomBlasSerialSize[i]));
2682
2683 bottomLevelAccelerationStructures[i]->setDeferredOperation(htSerialize, workerThreadsCount);
2684 bottomLevelAccelerationStructures[i]->serialize(vkd, device, *cmdBuffer, storage.get());
2685 bottomSerialized.push_back(storage);
2686
2687 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2688 {
2689 endCommandBuffer(vkd, *cmdBuffer);
2690
2691 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2692
2693 vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2694 beginCommandBuffer(vkd, *cmdBuffer, 0u);
2695 }
2696
2697 de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
2698 asCopy->setBuildType(m_data.buildType);
2699 asCopy->setBuildFlags(m_data.buildFlags);
2700 asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
2701 asCopy->setCreateGeneric(m_data.bottomGeneric);
2702 asCopy->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
2703 asCopy->setBuildWithoutGeometries(buildWithoutGeom);
2704 asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
2705 asCopy->setDeferredOperation(htSerialize, workerThreadsCount);
2706 asCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator, storage.get(), 0u);
2707 bottomLevelAccelerationStructureCopies.push_back(
2708 de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
2709 }
2710 break;
2711 }
2712 default:
2713 DE_ASSERT(false);
2714 }
2715 bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructureCopies;
2716 }
2717
2718 // build top level acceleration structures and their copies ( only when we are testing copying top level acceleration structures )
2719 bool topCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_TOP_ACCELERATION;
2720 bool topSerial = m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_TOP_ACCELERATION;
2721 VkBuildAccelerationStructureFlagsKHR topCompactFlags = (topCompact ? allowCompactionFlag : emptyCompactionFlag);
2722 VkBuildAccelerationStructureFlagsKHR topBuildFlags = m_data.buildFlags | topCompactFlags;
2723 std::vector<VkAccelerationStructureKHR> topLevelStructureHandles;
2724 std::vector<VkDeviceSize> topBlasCompactSize;
2725 std::vector<VkDeviceSize> topBlasSerialSize;
2726
2727 topLevelAccelerationStructure =
2728 sceneBuilder->initTopAccelerationStructure(m_context, m_data, *bottomLevelAccelerationStructuresPtr);
2729 topLevelAccelerationStructure->setBuildType(m_data.buildType);
2730 topLevelAccelerationStructure->setBuildFlags(topBuildFlags);
2731 topLevelAccelerationStructure->setBuildWithoutPrimitives(topNoPrimitives);
2732 topLevelAccelerationStructure->setUseArrayOfPointers(m_data.topUsesAOP);
2733 topLevelAccelerationStructure->setCreateGeneric(m_data.topGeneric);
2734 topLevelAccelerationStructure->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2735 topLevelAccelerationStructure->setInactiveInstances(inactiveInstances);
2736 topLevelAccelerationStructure->createAndBuild(vkd, device, *cmdBuffer, allocator);
2737 topLevelStructureHandles.push_back(*(topLevelAccelerationStructure->getPtr()));
2738
2739 if (topCompact)
2740 queryAccelerationStructureSize(
2741 vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolCompact.get(),
2742 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, topBlasCompactSize);
2743 if (topSerial)
2744 queryAccelerationStructureSize(
2745 vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolSerial.get(),
2746 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, topBlasSerialSize);
2747
2748 // if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU
2749 if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (topCompact || topSerial))
2750 {
2751 endCommandBuffer(vkd, *cmdBuffer);
2752
2753 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2754
2755 if (topCompact)
2756 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolCompact, 0u, uint32_t(topBlasCompactSize.size()),
2757 sizeof(VkDeviceSize) * topBlasCompactSize.size(),
2758 topBlasCompactSize.data(), sizeof(VkDeviceSize),
2759 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
2760 if (topSerial)
2761 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, uint32_t(topBlasSerialSize.size()),
2762 sizeof(VkDeviceSize) * topBlasSerialSize.size(),
2763 topBlasSerialSize.data(), sizeof(VkDeviceSize),
2764 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
2765
2766 vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2767 beginCommandBuffer(vkd, *cmdBuffer, 0u);
2768 }
2769
2770 const TopLevelAccelerationStructure *topLevelRayTracedPtr = topLevelAccelerationStructure.get();
2771 if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_TOP_ACCELERATION)
2772 {
2773 switch (m_data.operationType)
2774 {
2775 case OP_COPY:
2776 {
2777 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2778 topLevelAccelerationStructureCopy->setDeferredOperation(htCopy, workerThreadsCount);
2779 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2780 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2781 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2782 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2783 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2784 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2785 topLevelAccelerationStructureCopy->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2786 topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator,
2787 topLevelAccelerationStructure.get(), 0u, 0u);
2788 break;
2789 }
2790 case OP_COMPACT:
2791 {
2792 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2793 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2794 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2795 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2796 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2797 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2798 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2799 topLevelAccelerationStructureCopy->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2800 topLevelAccelerationStructureCopy->createAndCopyFrom(
2801 vkd, device, *cmdBuffer, allocator, topLevelAccelerationStructure.get(), topBlasCompactSize[0], 0u);
2802 break;
2803 }
2804 case OP_SERIALIZE:
2805 {
2806 de::SharedPtr<SerialStorage> storage(
2807 new SerialStorage(vkd, device, allocator, m_data.buildType, topBlasSerialSize[0]));
2808
2809 topLevelAccelerationStructure->setDeferredOperation(htSerialize, workerThreadsCount);
2810 topLevelAccelerationStructure->serialize(vkd, device, *cmdBuffer, storage.get());
2811 topSerialized.push_back(storage);
2812
2813 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2814 {
2815 endCommandBuffer(vkd, *cmdBuffer);
2816
2817 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2818
2819 vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2820 beginCommandBuffer(vkd, *cmdBuffer, 0u);
2821 }
2822
2823 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2824 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2825 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2826 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2827 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2828 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2829 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2830 topLevelAccelerationStructureCopy->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2831 topLevelAccelerationStructureCopy->setDeferredOperation(htSerialize, workerThreadsCount);
2832 topLevelAccelerationStructureCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator,
2833 storage.get(), 0u);
2834 break;
2835 }
2836 case OP_UPDATE:
2837 {
2838 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2839 topLevelAccelerationStructureCopy->create(vkd, device, allocator, 0u, 0u);
2840 // Update AS based on topLevelAccelerationStructure
2841 topLevelAccelerationStructureCopy->build(vkd, device, *cmdBuffer, topLevelAccelerationStructure.get());
2842 break;
2843 }
2844 case OP_UPDATE_IN_PLACE:
2845 {
2846 // Update in place
2847 topLevelAccelerationStructure->build(vkd, device, *cmdBuffer, topLevelAccelerationStructure.get());
2848 // Make a coppy
2849 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2850 topLevelAccelerationStructureCopy->setDeferredOperation(htCopy, workerThreadsCount);
2851 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2852 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2853 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2854 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2855 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2856 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2857 topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator,
2858 topLevelAccelerationStructure.get(), 0u, 0u);
2859 break;
2860 }
2861 default:
2862 DE_ASSERT(false);
2863 }
2864 topLevelRayTracedPtr = topLevelAccelerationStructureCopy.get();
2865 }
2866
2867 const VkMemoryBarrier preTraceMemoryBarrier =
2868 makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
2869 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
2870 &preTraceMemoryBarrier);
2871
2872 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
2873 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
2874 DE_NULL, // const void* pNext;
2875 1u, // uint32_t accelerationStructureCount;
2876 topLevelRayTracedPtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
2877 };
2878
2879 testConfiguration->fillCommandBuffer(m_context, m_data, *cmdBuffer, accelerationStructureWriteDescriptorSet,
2880 resultImageInfo);
2881
2882 const VkMemoryBarrier postTestMemoryBarrier =
2883 makeMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
2884 const VkMemoryBarrier postCopyMemoryBarrier =
2885 makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2886 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2887 &postTestMemoryBarrier);
2888
2889 vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u,
2890 &resultBufferImageRegion);
2891
2892 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2893 &postCopyMemoryBarrier);
2894 }
2895 endCommandBuffer(vkd, *cmdBuffer);
2896
2897 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2898
2899 invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(),
2900 resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
2901
2902 return resultBuffer;
2903 }
2904
iterateNoWorkers(void)2905 bool RayQueryASBasicTestInstance::iterateNoWorkers(void)
2906 {
2907 de::SharedPtr<TestConfiguration> testConfiguration = createTestConfiguration(m_data.shaderSourcePipeline);
2908 de::SharedPtr<SceneBuilder> sceneBuilder = de::SharedPtr<SceneBuilder>(new CheckerboardSceneBuilder());
2909
2910 const de::MovePtr<BufferWithMemory> buffer = runTest(testConfiguration.get(), sceneBuilder.get(), 0);
2911
2912 return testConfiguration->verifyImage(buffer.get(), m_context, m_data);
2913 }
2914
iterateWithWorkers(void)2915 bool RayQueryASBasicTestInstance::iterateWithWorkers(void)
2916 {
2917 de::SharedPtr<SceneBuilder> sceneBuilder = de::SharedPtr<SceneBuilder>(new CheckerboardSceneBuilder());
2918
2919 de::SharedPtr<TestConfiguration> testConfigurationS = createTestConfiguration(m_data.shaderSourcePipeline);
2920 de::MovePtr<BufferWithMemory> singleThreadBufferCPU = runTest(testConfigurationS.get(), sceneBuilder.get(), 0);
2921 const bool singleThreadValidation = testConfigurationS->verifyImage(singleThreadBufferCPU.get(), m_context, m_data);
2922 testConfigurationS.clear();
2923
2924 de::SharedPtr<TestConfiguration> testConfigurationM = createTestConfiguration(m_data.shaderSourcePipeline);
2925 de::MovePtr<BufferWithMemory> multiThreadBufferCPU =
2926 runTest(testConfigurationM.get(), sceneBuilder.get(), m_data.workerThreadsCount);
2927 const bool multiThreadValidation = testConfigurationM->verifyImage(multiThreadBufferCPU.get(), m_context, m_data);
2928 testConfigurationM.clear();
2929
2930 const uint32_t result = singleThreadValidation && multiThreadValidation;
2931
2932 return result;
2933 }
2934
iterate(void)2935 tcu::TestStatus RayQueryASBasicTestInstance::iterate(void)
2936 {
2937 bool result;
2938 if (m_data.workerThreadsCount != 0)
2939 result = iterateWithWorkers();
2940 else
2941 result = iterateNoWorkers();
2942
2943 if (result)
2944 return tcu::TestStatus::pass("Pass");
2945 else
2946 return tcu::TestStatus::fail("Fail");
2947 }
2948
2949 // Tests dynamic indexing of acceleration structures
2950 class RayQueryASDynamicIndexingTestCase : public TestCase
2951 {
2952 public:
2953 RayQueryASDynamicIndexingTestCase(tcu::TestContext &context, const char *name);
2954 ~RayQueryASDynamicIndexingTestCase(void) = default;
2955
2956 void checkSupport(Context &context) const override;
2957 void initPrograms(SourceCollections &programCollection) const override;
2958 TestInstance *createInstance(Context &context) const override;
2959 };
2960
2961 class RayQueryASDynamicIndexingTestInstance : public TestInstance
2962 {
2963 public:
2964 RayQueryASDynamicIndexingTestInstance(Context &context);
2965 ~RayQueryASDynamicIndexingTestInstance(void) = default;
2966 tcu::TestStatus iterate(void) override;
2967 };
2968
RayQueryASDynamicIndexingTestCase(tcu::TestContext & context,const char * name)2969 RayQueryASDynamicIndexingTestCase::RayQueryASDynamicIndexingTestCase(tcu::TestContext &context, const char *name)
2970 : TestCase(context, name)
2971 {
2972 }
2973
checkSupport(Context & context) const2974 void RayQueryASDynamicIndexingTestCase::checkSupport(Context &context) const
2975 {
2976 commonASTestsCheckSupport(context);
2977 context.requireDeviceFunctionality("VK_EXT_descriptor_indexing");
2978 }
2979
initPrograms(SourceCollections & programCollection) const2980 void RayQueryASDynamicIndexingTestCase::initPrograms(SourceCollections &programCollection) const
2981 {
2982 const vk::SpirVAsmBuildOptions spvBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
2983
2984 // compute shader is defined in spir-v as it requires possing pointer to TLAS that was read from ssbo;
2985 // original spir-v code was generated using following glsl code but resulting spir-v code was modiifed
2986
2987 // #version 460 core
2988 // #extension GL_EXT_ray_query : require
2989 // #extension GL_EXT_nonuniform_qualifier : enable
2990
2991 // #define ARRAY_SIZE 500
2992 // layout(set = 0, binding = 0) uniform accelerationStructureEXT tlasArray[ARRAY_SIZE];
2993 // layout(set = 0, binding = 1) readonly buffer topLevelASPointers {
2994 // uvec2 ptr[];
2995 // } tlasPointers;
2996 // layout(set = 0, binding = 2) readonly buffer topLevelASIndices {
2997 // uint idx[];
2998 // } tlasIndices;
2999 // layout(set = 0, binding = 3, std430) writeonly buffer Result {
3000 // uint value[];
3001 // } result;
3002
3003 // void main()
3004 // {
3005 // float tmin = 0.0;
3006 // float tmax = 2.0;
3007 // vec3 origin = vec3(0.25f, 0.5f, 1.0);
3008 // vec3 direction = vec3(0.0,0.0,-1.0);
3009 // uint tlasIndex = tlasIndices.idx[nonuniformEXT(gl_GlobalInvocationID.x)];
3010
3011 // rayQueryEXT rq;
3012 // rayQueryInitializeEXT(rq, tlasArray[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, origin, tmin, direction, tmax);
3013 // atomicAdd(result.value[nonuniformEXT(gl_GlobalInvocationID.x)], 2);
3014
3015 // if (rayQueryProceedEXT(rq))
3016 // {
3017 // if (rayQueryGetIntersectionTypeEXT(rq, false) == gl_RayQueryCandidateIntersectionTriangleEXT)
3018 // atomicAdd(result.value[nonuniformEXT(gl_GlobalInvocationID.x + gl_NumWorkGroups.x)], 3);
3019 // }
3020
3021 // //rayQueryInitializeEXT(rq, tlasArray[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, origin, tmin, direction, tmax);
3022 // rayQueryInitializeEXT(rq, *tlasPointers.ptr[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, origin, tmin, direction, tmax);
3023 // atomicAdd(result.value[nonuniformEXT(gl_GlobalInvocationID.x + gl_NumWorkGroups.x * 2)], 5);
3024
3025 // if (rayQueryProceedEXT(rq))
3026 // {
3027 // if (rayQueryGetIntersectionTypeEXT(rq, false) == gl_RayQueryCandidateIntersectionTriangleEXT)
3028 // atomicAdd(result.value[nonuniformEXT(gl_GlobalInvocationID.x + gl_NumWorkGroups.x * 3)], 7);
3029 // }
3030 // }
3031
3032 const std::string compSource =
3033 "OpCapability Shader\n"
3034 "OpCapability RayQueryKHR\n"
3035 "OpCapability ShaderNonUniform\n"
3036 "OpExtension \"SPV_EXT_descriptor_indexing\"\n"
3037 "OpExtension \"SPV_KHR_ray_query\"\n"
3038 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
3039 "OpMemoryModel Logical GLSL450\n"
3040 "OpEntryPoint GLCompute %4 \"main\" %var_index_ssbo %33 %var_as_arr_uni_ptr %64 %83 %var_as_pointers_ssbo\n"
3041 "OpExecutionMode %4 LocalSize 1 1 1\n"
3042 "OpDecorate %25 ArrayStride 4\n"
3043 "OpMemberDecorate %26 0 NonWritable\n"
3044 "OpMemberDecorate %26 0 Offset 0\n"
3045 "OpDecorate %26 Block\n"
3046 "OpDecorate %var_index_ssbo DescriptorSet 0\n"
3047 "OpDecorate %var_index_ssbo Binding 2\n"
3048 "OpDecorate %33 BuiltIn GlobalInvocationId\n"
3049 "OpDecorate %38 NonUniform\n"
3050 "OpDecorate %40 NonUniform\n"
3051 "OpDecorate %41 NonUniform\n"
3052 "OpDecorate %var_as_arr_uni_ptr DescriptorSet 0\n"
3053 "OpDecorate %var_as_arr_uni_ptr Binding 0\n"
3054 "OpDecorate %51 NonUniform\n"
3055 "OpDecorate %53 NonUniform\n"
3056 "OpDecorate %54 NonUniform\n"
3057 "OpDecorate %61 ArrayStride 4\n"
3058 "OpMemberDecorate %62 0 NonReadable\n"
3059 "OpMemberDecorate %62 0 Offset 0\n"
3060 "OpDecorate %62 Block\n"
3061 "OpDecorate %64 DescriptorSet 0\n"
3062 "OpDecorate %64 Binding 3\n"
3063 "OpDecorate %67 NonUniform\n"
3064 "OpDecorate %83 BuiltIn NumWorkgroups\n"
3065 "OpDecorate %87 NonUniform\n"
3066 "OpDecorate %as_index NonUniform\n"
3067 "OpDecorate %as_device_addres NonUniform\n"
3068 "OpDecorate %105 NonUniform\n"
3069 "OpDecorate %122 NonUniform\n"
3070 "OpDecorate %127 ArrayStride 8\n"
3071 "OpMemberDecorate %128 0 NonWritable\n"
3072 "OpMemberDecorate %128 0 Offset 0\n"
3073 "OpDecorate %128 Block\n"
3074 "OpDecorate %var_as_pointers_ssbo DescriptorSet 0\n"
3075 "OpDecorate %var_as_pointers_ssbo Binding 1\n"
3076 "%2 = OpTypeVoid\n"
3077 "%3 = OpTypeFunction %2\n"
3078 "%6 = OpTypeFloat 32\n"
3079 "%7 = OpTypePointer Function %6\n"
3080 "%9 = OpConstant %6 0\n"
3081 "%11 = OpConstant %6 2\n"
3082 "%12 = OpTypeVector %6 3\n"
3083 "%13 = OpTypePointer Function %12\n"
3084 "%15 = OpConstant %6 0.25\n"
3085 "%16 = OpConstant %6 0.5\n"
3086 "%17 = OpConstant %6 1\n"
3087 "%18 = OpConstantComposite %12 %15 %16 %17\n"
3088 "%20 = OpConstant %6 -1\n"
3089 "%21 = OpConstantComposite %12 %9 %9 %20\n"
3090 "%type_uint32 = OpTypeInt 32 0\n"
3091 "%23 = OpTypePointer Function %type_uint32\n"
3092 "%25 = OpTypeRuntimeArray %type_uint32\n"
3093 "%26 = OpTypeStruct %25\n"
3094 "%27 = OpTypePointer StorageBuffer %26\n"
3095 "%var_index_ssbo = OpVariable %27 StorageBuffer\n"
3096 "%29 = OpTypeInt 32 1\n"
3097 "%c_int32_0 = OpConstant %29 0\n"
3098 "%31 = OpTypeVector %type_uint32 3\n"
3099 "%32 = OpTypePointer Input %31\n"
3100 "%33 = OpVariable %32 Input\n"
3101 "%34 = OpConstant %type_uint32 0\n"
3102 "%35 = OpTypePointer Input %type_uint32\n"
3103 "%type_uint32_ssbo_ptr = OpTypePointer StorageBuffer %type_uint32\n"
3104 "%42 = OpTypeRayQueryKHR\n"
3105 "%43 = OpTypePointer Function %42\n"
3106 "%type_as = OpTypeAccelerationStructureKHR\n"
3107 "%46 = OpConstant %type_uint32 500\n"
3108 "%type_as_arr = OpTypeArray %type_as %46\n"
3109 "%type_as_arr_uni_ptr = OpTypePointer UniformConstant %type_as_arr\n"
3110 "%var_as_arr_uni_ptr = OpVariable %type_as_arr_uni_ptr UniformConstant\n"
3111 "%type_as_uni_ptr = OpTypePointer UniformConstant %type_as\n"
3112 "%55 = OpConstant %type_uint32 16\n"
3113 "%56 = OpConstant %type_uint32 255\n"
3114 "%61 = OpTypeRuntimeArray %type_uint32\n"
3115 "%62 = OpTypeStruct %61\n"
3116 "%63 = OpTypePointer StorageBuffer %62\n"
3117 "%64 = OpVariable %63 StorageBuffer\n"
3118 "%69 = OpConstant %type_uint32 2\n"
3119 "%70 = OpConstant %type_uint32 1\n"
3120 "%72 = OpTypeBool\n"
3121 "%76 = OpConstantFalse %72\n"
3122 "%83 = OpVariable %32 Input\n"
3123 "%89 = OpConstant %type_uint32 3\n"
3124 "%107 = OpConstant %type_uint32 5\n"
3125 "%124 = OpConstant %type_uint32 7\n"
3126
3127 // <changed_section>
3128 "%v2uint = OpTypeVector %type_uint32 2\n"
3129 "%127 = OpTypeRuntimeArray %v2uint\n"
3130 "%128 = OpTypeStruct %127\n"
3131 "%129 = OpTypePointer StorageBuffer %128\n"
3132 "%var_as_pointers_ssbo = OpVariable %129 StorageBuffer\n"
3133 "%type_uint64_ssbo_ptr = OpTypePointer StorageBuffer %v2uint\n"
3134 // </changed_section>
3135
3136 // void main()
3137 "%4 = OpFunction %2 None %3\n"
3138 "%5 = OpLabel\n"
3139 "%8 = OpVariable %7 Function\n"
3140 "%10 = OpVariable %7 Function\n"
3141 "%14 = OpVariable %13 Function\n"
3142 "%19 = OpVariable %13 Function\n"
3143 "%24 = OpVariable %23 Function\n"
3144 "%var_ray_query = OpVariable %43 Function\n"
3145 "OpStore %8 %9\n"
3146 "OpStore %10 %11\n"
3147 "OpStore %14 %18\n"
3148 "OpStore %19 %21\n"
3149 "%36 = OpAccessChain %35 %33 %34\n"
3150 "%37 = OpLoad %type_uint32 %36\n"
3151 "%38 = OpCopyObject %type_uint32 %37\n"
3152 "%40 = OpAccessChain %type_uint32_ssbo_ptr %var_index_ssbo %c_int32_0 %38\n"
3153 "%41 = OpLoad %type_uint32 %40\n"
3154 "OpStore %24 %41\n"
3155
3156 // rayQueryInitializeEXT using AS that was read from array
3157 "%50 = OpLoad %type_uint32 %24\n"
3158 "%51 = OpCopyObject %type_uint32 %50\n"
3159 "%53 = OpAccessChain %type_as_uni_ptr %var_as_arr_uni_ptr %51\n"
3160 "%54 = OpLoad %type_as %53\n"
3161 "%57 = OpLoad %12 %14\n"
3162 "%58 = OpLoad %6 %8\n"
3163 "%59 = OpLoad %12 %19\n"
3164 "%60 = OpLoad %6 %10\n"
3165 "OpRayQueryInitializeKHR %var_ray_query %54 %55 %56 %57 %58 %59 %60\n"
3166
3167 "%65 = OpAccessChain %35 %33 %34\n"
3168 "%66 = OpLoad %type_uint32 %65\n"
3169 "%67 = OpCopyObject %type_uint32 %66\n"
3170 "%68 = OpAccessChain %type_uint32_ssbo_ptr %64 %c_int32_0 %67\n"
3171 "%71 = OpAtomicIAdd %type_uint32 %68 %70 %34 %69\n"
3172
3173 "%73 = OpRayQueryProceedKHR %72 %var_ray_query\n"
3174 "OpSelectionMerge %75 None\n"
3175 "OpBranchConditional %73 %74 %75\n"
3176 "%74 = OpLabel\n"
3177
3178 "%77 = OpRayQueryGetIntersectionTypeKHR %type_uint32 %var_ray_query %c_int32_0\n"
3179 "%78 = OpIEqual %72 %77 %34\n"
3180 "OpSelectionMerge %80 None\n"
3181 "OpBranchConditional %78 %79 %80\n"
3182 "%79 = OpLabel\n"
3183 "%81 = OpAccessChain %35 %33 %34\n"
3184 "%82 = OpLoad %type_uint32 %81\n"
3185 "%84 = OpAccessChain %35 %83 %34\n"
3186 "%85 = OpLoad %type_uint32 %84\n"
3187 "%86 = OpIAdd %type_uint32 %82 %85\n"
3188 "%87 = OpCopyObject %type_uint32 %86\n"
3189 "%88 = OpAccessChain %type_uint32_ssbo_ptr %64 %c_int32_0 %87\n"
3190 "%90 = OpAtomicIAdd %type_uint32 %88 %70 %34 %89\n"
3191 "OpBranch %80\n"
3192 "%80 = OpLabel\n"
3193 "OpBranch %75\n"
3194 "%75 = OpLabel\n"
3195
3196 // rayQueryInitializeEXT using pointer to AS
3197 "%91 = OpLoad %type_uint32 %24\n"
3198 "%as_index = OpCopyObject %type_uint32 %91\n"
3199
3200 // <changed_section>
3201 "%as_device_addres_ptr = OpAccessChain %type_uint64_ssbo_ptr %var_as_pointers_ssbo %c_int32_0 %as_index\n"
3202 "%as_device_addres = OpLoad %v2uint %as_device_addres_ptr\n"
3203 "%as_to_use = OpConvertUToAccelerationStructureKHR %type_as %as_device_addres\n"
3204 // </changed_section>
3205
3206 "%95 = OpLoad %12 %14\n"
3207 "%96 = OpLoad %6 %8\n"
3208 "%97 = OpLoad %12 %19\n"
3209 "%98 = OpLoad %6 %10\n"
3210 "OpRayQueryInitializeKHR %var_ray_query %as_to_use %55 %56 %95 %96 %97 %98\n"
3211
3212 "%99 = OpAccessChain %35 %33 %34\n"
3213 "%100 = OpLoad %type_uint32 %99\n"
3214 "%101 = OpAccessChain %35 %83 %34\n"
3215 "%102 = OpLoad %type_uint32 %101\n"
3216 "%103 = OpIMul %type_uint32 %102 %69\n"
3217 "%104 = OpIAdd %type_uint32 %100 %103\n"
3218 "%105 = OpCopyObject %type_uint32 %104\n"
3219 "%106 = OpAccessChain %type_uint32_ssbo_ptr %64 %c_int32_0 %105\n"
3220 "%108 = OpAtomicIAdd %type_uint32 %106 %70 %34 %107\n"
3221
3222 "%109 = OpRayQueryProceedKHR %72 %var_ray_query\n"
3223 "OpSelectionMerge %111 None\n"
3224 "OpBranchConditional %109 %110 %111\n"
3225 "%110 = OpLabel\n"
3226
3227 "%112 = OpRayQueryGetIntersectionTypeKHR %type_uint32 %var_ray_query %c_int32_0\n"
3228 "%113 = OpIEqual %72 %112 %34\n"
3229 "OpSelectionMerge %115 None\n"
3230 "OpBranchConditional %113 %114 %115\n"
3231 "%114 = OpLabel\n"
3232 "%116 = OpAccessChain %35 %33 %34\n"
3233 "%117 = OpLoad %type_uint32 %116\n"
3234 "%118 = OpAccessChain %35 %83 %34\n"
3235 "%119 = OpLoad %type_uint32 %118\n"
3236 "%120 = OpIMul %type_uint32 %119 %89\n"
3237 "%121 = OpIAdd %type_uint32 %117 %120\n"
3238 "%122 = OpCopyObject %type_uint32 %121\n"
3239 "%123 = OpAccessChain %type_uint32_ssbo_ptr %64 %c_int32_0 %122\n"
3240 "%125 = OpAtomicIAdd %type_uint32 %123 %70 %34 %124\n"
3241 "OpBranch %115\n"
3242 "%115 = OpLabel\n"
3243 "OpBranch %111\n"
3244 "%111 = OpLabel\n"
3245 "OpReturn\n"
3246 "OpFunctionEnd\n";
3247
3248 programCollection.spirvAsmSources.add("comp") << compSource << spvBuildOptions;
3249 }
3250
createInstance(Context & context) const3251 TestInstance *RayQueryASDynamicIndexingTestCase::createInstance(Context &context) const
3252 {
3253 return new RayQueryASDynamicIndexingTestInstance(context);
3254 }
3255
RayQueryASDynamicIndexingTestInstance(Context & context)3256 RayQueryASDynamicIndexingTestInstance::RayQueryASDynamicIndexingTestInstance(Context &context)
3257 : vkt::TestInstance(context)
3258 {
3259 }
3260
iterate(void)3261 tcu::TestStatus RayQueryASDynamicIndexingTestInstance::iterate(void)
3262 {
3263 const DeviceInterface &vkd = m_context.getDeviceInterface();
3264 const VkDevice device = m_context.getDevice();
3265 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
3266 const VkQueue queue = m_context.getUniversalQueue();
3267 Allocator &allocator = m_context.getDefaultAllocator();
3268 const uint32_t tlasCount = 500; // changing this will require also changing shaders
3269 const uint32_t activeTlasCount = 32; // number of tlas out of <tlasCount> that will be active
3270
3271 const Move<VkDescriptorSetLayout> descriptorSetLayout =
3272 DescriptorSetLayoutBuilder()
3273 .addArrayBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount, VK_SHADER_STAGE_COMPUTE_BIT)
3274 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
3275 VK_SHADER_STAGE_COMPUTE_BIT) // pointers to all acceleration structures
3276 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
3277 VK_SHADER_STAGE_COMPUTE_BIT) // ssbo with indices of all acceleration structures
3278 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) // ssbo with result values
3279 .build(vkd, device);
3280
3281 const Move<VkDescriptorPool> descriptorPool =
3282 DescriptorPoolBuilder()
3283 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount)
3284 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
3285 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
3286 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
3287 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
3288 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
3289
3290 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
3291 Move<VkShaderModule> shaderModule =
3292 createShaderModule(vkd, device, m_context.getBinaryCollection().get("comp"), 0u);
3293 const VkComputePipelineCreateInfo pipelineCreateInfo{
3294 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType
3295 DE_NULL, // const void* pNext
3296 0u, // VkPipelineCreateFlags flags
3297 { // VkPipelineShaderStageCreateInfo stage
3298 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, DE_NULL, (VkPipelineShaderStageCreateFlags)0,
3299 VK_SHADER_STAGE_COMPUTE_BIT, *shaderModule, "main", DE_NULL},
3300 *pipelineLayout, // VkPipelineLayout layout
3301 DE_NULL, // VkPipeline basePipelineHandle
3302 0, // int32_t basePipelineIndex
3303 };
3304
3305 Move<VkPipeline> pipeline = createComputePipeline(vkd, device, DE_NULL, &pipelineCreateInfo);
3306
3307 const VkDeviceSize pointerBufferSize = tlasCount * sizeof(VkDeviceAddress);
3308 const VkBufferCreateInfo pointerBufferCreateInfo =
3309 makeBufferCreateInfo(pointerBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3310 de::MovePtr<BufferWithMemory> pointerBuffer = de::MovePtr<BufferWithMemory>(
3311 new BufferWithMemory(vkd, device, allocator, pointerBufferCreateInfo,
3312 MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress));
3313
3314 const VkDeviceSize indicesBufferSize = activeTlasCount * sizeof(uint32_t);
3315 const VkBufferCreateInfo indicesBufferCreateInfo =
3316 makeBufferCreateInfo(indicesBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3317 de::MovePtr<BufferWithMemory> indicesBuffer = de::MovePtr<BufferWithMemory>(
3318 new BufferWithMemory(vkd, device, allocator, indicesBufferCreateInfo, MemoryRequirement::HostVisible));
3319
3320 const VkDeviceSize resultBufferSize = activeTlasCount * sizeof(uint32_t) * 4;
3321 const VkBufferCreateInfo resultBufferCreateInfo =
3322 makeBufferCreateInfo(resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
3323 de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(
3324 new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
3325
3326 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
3327 const Move<VkCommandBuffer> cmdBuffer =
3328 allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3329
3330 de::SharedPtr<BottomLevelAccelerationStructure> blas =
3331 de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
3332 std::vector<de::MovePtr<TopLevelAccelerationStructure>> tlasVect(tlasCount);
3333 std::vector<VkDeviceAddress> tlasPtrVect(tlasCount);
3334 std::vector<VkAccelerationStructureKHR> tlasVkVect;
3335
3336 // randomly scatter AS indices across the range (number of them should be equal to the max subgroup size)
3337 deRandom rnd;
3338 deRandom_init(&rnd, 123);
3339 std::set<uint32_t> asIndicesSet;
3340 while (asIndicesSet.size() < activeTlasCount)
3341 asIndicesSet.insert(deRandom_getUint32(&rnd) % tlasCount);
3342
3343 // fill indices buffer
3344 uint32_t helperIndex = 0;
3345 auto &indicesBufferAlloc = indicesBuffer->getAllocation();
3346 uint32_t *indicesBufferPtr = reinterpret_cast<uint32_t *>(indicesBufferAlloc.getHostPtr());
3347 std::for_each(asIndicesSet.begin(), asIndicesSet.end(),
3348 [&helperIndex, indicesBufferPtr](const uint32_t &index) { indicesBufferPtr[helperIndex++] = index; });
3349 vk::flushAlloc(vkd, device, indicesBufferAlloc);
3350
3351 // clear result buffer
3352 auto &resultBufferAlloc = resultBuffer->getAllocation();
3353 void *resultBufferPtr = resultBufferAlloc.getHostPtr();
3354 deMemset(resultBufferPtr, 0, static_cast<size_t>(resultBufferSize));
3355 vk::flushAlloc(vkd, device, resultBufferAlloc);
3356
3357 beginCommandBuffer(vkd, *cmdBuffer, 0u);
3358 {
3359 // build bottom level acceleration structure
3360 blas->setGeometryData(
3361 {
3362 {0.0, 0.0, 0.0},
3363 {1.0, 0.0, 0.0},
3364 {0.0, 1.0, 0.0},
3365 },
3366 true, 0u);
3367
3368 blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
3369
3370 // build top level acceleration structures
3371 for (uint32_t tlasIndex = 0; tlasIndex < tlasCount; ++tlasIndex)
3372 {
3373 auto &tlas = tlasVect[tlasIndex];
3374 tlas = makeTopLevelAccelerationStructure();
3375 tlas->setInstanceCount(1);
3376 tlas->addInstance(blas);
3377 if (!asIndicesSet.count(tlasIndex))
3378 {
3379 // tlas that are not in asIndicesSet should be empty but it is hard to do
3380 // that with current cts utils so we are marking them as inactive instead
3381 tlas->setInactiveInstances(true);
3382 }
3383 tlas->createAndBuild(vkd, device, *cmdBuffer, allocator);
3384
3385 // get acceleration structure device address
3386 const VkAccelerationStructureDeviceAddressInfoKHR addressInfo = {
3387 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR, // VkStructureType sType
3388 DE_NULL, // const void* pNext
3389 *tlas->getPtr() // VkAccelerationStructureKHR accelerationStructure
3390 };
3391 VkDeviceAddress vkda = vkd.getAccelerationStructureDeviceAddressKHR(device, &addressInfo);
3392 tlasPtrVect[tlasIndex] = vkda;
3393 }
3394
3395 // fill pointer buffer
3396 vkd.cmdUpdateBuffer(*cmdBuffer, **pointerBuffer, 0, pointerBufferSize, tlasPtrVect.data());
3397
3398 // wait for data transfers
3399 const VkMemoryBarrier uploadBarrier =
3400 makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
3401 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
3402 &uploadBarrier, 1u);
3403
3404 // wait for as build
3405 const VkMemoryBarrier asBuildBarrier = makeMemoryBarrier(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
3406 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR);
3407 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
3408 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, &asBuildBarrier, 1u);
3409
3410 tlasVkVect.reserve(tlasCount);
3411 for (auto &tlas : tlasVect)
3412 tlasVkVect.push_back(*tlas->getPtr());
3413
3414 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
3415 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
3416 DE_NULL, // const void* pNext;
3417 tlasCount, // uint32_t accelerationStructureCount;
3418 tlasVkVect.data(), // const VkAccelerationStructureKHR* pAccelerationStructures;
3419 };
3420
3421 const vk::VkDescriptorBufferInfo pointerBufferInfo =
3422 makeDescriptorBufferInfo(**pointerBuffer, 0u, VK_WHOLE_SIZE);
3423 const vk::VkDescriptorBufferInfo indicesBufferInfo =
3424 makeDescriptorBufferInfo(**indicesBuffer, 0u, VK_WHOLE_SIZE);
3425 const vk::VkDescriptorBufferInfo resultInfo = makeDescriptorBufferInfo(**resultBuffer, 0u, VK_WHOLE_SIZE);
3426
3427 DescriptorSetUpdateBuilder()
3428 .writeArray(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
3429 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount,
3430 &accelerationStructureWriteDescriptorSet)
3431 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
3432 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &pointerBufferInfo)
3433 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u),
3434 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indicesBufferInfo)
3435 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(3u),
3436 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo)
3437 .update(vkd, device);
3438
3439 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1,
3440 &descriptorSet.get(), 0, DE_NULL);
3441
3442 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
3443
3444 vkd.cmdDispatch(*cmdBuffer, activeTlasCount, 1, 1);
3445
3446 const VkMemoryBarrier postTraceMemoryBarrier =
3447 makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
3448 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3449 &postTraceMemoryBarrier);
3450 }
3451 endCommandBuffer(vkd, *cmdBuffer);
3452
3453 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
3454
3455 invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(),
3456 resultBuffer->getAllocation().getOffset(), resultBufferSize);
3457
3458 // verify result buffer
3459 uint32_t failures = 0;
3460 const uint32_t *resultPtr = reinterpret_cast<uint32_t *>(resultBuffer->getAllocation().getHostPtr());
3461 for (uint32_t index = 0; index < activeTlasCount; ++index)
3462 {
3463 failures += (resultPtr[0 * activeTlasCount + index] != 2) + (resultPtr[1 * activeTlasCount + index] != 3) +
3464 (resultPtr[2 * activeTlasCount + index] != 5) + (resultPtr[3 * activeTlasCount + index] != 7);
3465 }
3466
3467 if (failures)
3468 return tcu::TestStatus::fail(de::toString(failures) + " failures, " +
3469 de::toString(4 * activeTlasCount - failures) + " are ok");
3470 return tcu::TestStatus::pass("Pass");
3471 }
3472
3473 } // namespace
3474
3475 /********************/
3476
addBasicBuildingTests(tcu::TestCaseGroup * group)3477 void addBasicBuildingTests(tcu::TestCaseGroup *group)
3478 {
3479 struct ShaderSourceTypeData
3480 {
3481 ShaderSourceType shaderSourceType;
3482 ShaderSourcePipeline shaderSourcePipeline;
3483 const char *name;
3484 } shaderSourceTypes[] = {
3485 {
3486 SST_FRAGMENT_SHADER,
3487 SSP_GRAPHICS_PIPELINE,
3488 "fragment_shader",
3489 },
3490 {
3491 SST_COMPUTE_SHADER,
3492 SSP_COMPUTE_PIPELINE,
3493 "compute_shader",
3494 },
3495 {
3496 SST_CLOSEST_HIT_SHADER,
3497 SSP_RAY_TRACING_PIPELINE,
3498 "chit_shader",
3499 },
3500 };
3501
3502 struct
3503 {
3504 vk::VkAccelerationStructureBuildTypeKHR buildType;
3505 const char *name;
3506 } buildTypes[] = {
3507 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
3508 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
3509 };
3510
3511 struct
3512 {
3513 BottomTestType testType;
3514 bool usesAOP;
3515 const char *name;
3516 } bottomTestTypes[] = {
3517 {BottomTestType::TRIANGLES, false, "triangles"},
3518 {BottomTestType::TRIANGLES, true, "triangles_aop"},
3519 {BottomTestType::AABBS, false, "aabbs"},
3520 {BottomTestType::AABBS, true, "aabbs_aop"},
3521 };
3522
3523 struct
3524 {
3525 TopTestType testType;
3526 bool usesAOP;
3527 const char *name;
3528 } topTestTypes[] = {
3529 {TopTestType::IDENTICAL_INSTANCES, false, "identical_instances"},
3530 {TopTestType::IDENTICAL_INSTANCES, true, "identical_instances_aop"},
3531 {TopTestType::DIFFERENT_INSTANCES, false, "different_instances"},
3532 {TopTestType::DIFFERENT_INSTANCES, true, "different_instances_aop"},
3533 };
3534
3535 struct BuildFlagsData
3536 {
3537 VkBuildAccelerationStructureFlagsKHR flags;
3538 const char *name;
3539 };
3540
3541 BuildFlagsData optimizationTypes[] = {
3542 {VkBuildAccelerationStructureFlagsKHR(0u), "0"},
3543 {VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, "fasttrace"},
3544 {VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, "fastbuild"},
3545 };
3546
3547 BuildFlagsData updateTypes[] = {
3548 {VkBuildAccelerationStructureFlagsKHR(0u), "0"},
3549 {VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, "update"},
3550 };
3551
3552 BuildFlagsData compactionTypes[] = {
3553 {VkBuildAccelerationStructureFlagsKHR(0u), "0"},
3554 {VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, "compaction"},
3555 };
3556
3557 BuildFlagsData lowMemoryTypes[] = {
3558 {VkBuildAccelerationStructureFlagsKHR(0u), "0"},
3559 {VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, "lowmemory"},
3560 };
3561
3562 struct
3563 {
3564 bool padVertices;
3565 const char *name;
3566 } paddingType[] = {
3567 {false, "nopadding"},
3568 {true, "padded"},
3569 };
3570
3571 struct
3572 {
3573 bool topGeneric;
3574 bool bottomGeneric;
3575 const char *suffix;
3576 } createGenericParams[] = {
3577 {false, false, ""},
3578 {false, true, "_bottomgeneric"},
3579 {true, false, "_topgeneric"},
3580 {true, true, "_bothgeneric"},
3581 };
3582
3583 // In order not to create thousands of new test variants for unbound buffer memory on acceleration structure creation, we will
3584 // set these options on some of the tests.
3585 de::ModCounter32 unboundedCreationBottomCounter(3u);
3586 de::ModCounter32 unboundedCreationTopCounter(7u);
3587
3588 for (size_t shaderSourceNdx = 0; shaderSourceNdx < DE_LENGTH_OF_ARRAY(shaderSourceTypes); ++shaderSourceNdx)
3589 {
3590 de::MovePtr<tcu::TestCaseGroup> sourceTypeGroup(
3591 new tcu::TestCaseGroup(group->getTestContext(), shaderSourceTypes[shaderSourceNdx].name));
3592
3593 for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
3594 {
3595 de::MovePtr<tcu::TestCaseGroup> buildGroup(
3596 new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
3597
3598 for (size_t bottomNdx = 0; bottomNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++bottomNdx)
3599 {
3600 de::MovePtr<tcu::TestCaseGroup> bottomGroup(
3601 new tcu::TestCaseGroup(group->getTestContext(), bottomTestTypes[bottomNdx].name));
3602
3603 for (size_t topNdx = 0; topNdx < DE_LENGTH_OF_ARRAY(topTestTypes); ++topNdx)
3604 {
3605 de::MovePtr<tcu::TestCaseGroup> topGroup(
3606 new tcu::TestCaseGroup(group->getTestContext(), topTestTypes[topNdx].name));
3607
3608 for (int paddingTypeIdx = 0; paddingTypeIdx < DE_LENGTH_OF_ARRAY(paddingType); ++paddingTypeIdx)
3609 {
3610 de::MovePtr<tcu::TestCaseGroup> paddingTypeGroup(
3611 new tcu::TestCaseGroup(group->getTestContext(), paddingType[paddingTypeIdx].name));
3612
3613 for (size_t optimizationNdx = 0; optimizationNdx < DE_LENGTH_OF_ARRAY(optimizationTypes);
3614 ++optimizationNdx)
3615 {
3616 for (size_t updateNdx = 0; updateNdx < DE_LENGTH_OF_ARRAY(updateTypes); ++updateNdx)
3617 {
3618 for (size_t compactionNdx = 0; compactionNdx < DE_LENGTH_OF_ARRAY(compactionTypes);
3619 ++compactionNdx)
3620 {
3621 for (size_t lowMemoryNdx = 0; lowMemoryNdx < DE_LENGTH_OF_ARRAY(lowMemoryTypes);
3622 ++lowMemoryNdx)
3623 {
3624 for (int createGenericIdx = 0;
3625 createGenericIdx < DE_LENGTH_OF_ARRAY(createGenericParams);
3626 ++createGenericIdx)
3627 {
3628 std::string testName =
3629 std::string(optimizationTypes[optimizationNdx].name) + "_" +
3630 std::string(updateTypes[updateNdx].name) + "_" +
3631 std::string(compactionTypes[compactionNdx].name) + "_" +
3632 std::string(lowMemoryTypes[lowMemoryNdx].name) +
3633 std::string(createGenericParams[createGenericIdx].suffix);
3634
3635 const bool unboundedCreationBottom =
3636 (static_cast<uint32_t>(unboundedCreationBottomCounter++) == 0u);
3637 const bool unboundedCreationTop =
3638 (static_cast<uint32_t>(unboundedCreationTopCounter++) == 0u);
3639
3640 TestParams testParams{
3641 shaderSourceTypes[shaderSourceNdx].shaderSourceType,
3642 shaderSourceTypes[shaderSourceNdx].shaderSourcePipeline,
3643 buildTypes[buildTypeNdx].buildType,
3644 VK_FORMAT_R32G32B32_SFLOAT,
3645 paddingType[paddingTypeIdx].padVertices,
3646 VK_INDEX_TYPE_NONE_KHR,
3647 bottomTestTypes[bottomNdx].testType,
3648 InstanceCullFlags::NONE,
3649 bottomTestTypes[bottomNdx].usesAOP,
3650 createGenericParams[createGenericIdx].bottomGeneric,
3651 unboundedCreationBottom,
3652 topTestTypes[topNdx].testType,
3653 topTestTypes[topNdx].usesAOP,
3654 createGenericParams[createGenericIdx].topGeneric,
3655 unboundedCreationTop,
3656 optimizationTypes[optimizationNdx].flags |
3657 updateTypes[updateNdx].flags |
3658 compactionTypes[compactionNdx].flags |
3659 lowMemoryTypes[lowMemoryNdx].flags,
3660 OT_NONE,
3661 OP_NONE,
3662 TEST_WIDTH,
3663 TEST_HEIGHT,
3664 0u,
3665 EmptyAccelerationStructureCase::NOT_EMPTY,
3666 };
3667 paddingTypeGroup->addChild(new RayQueryASBasicTestCase(
3668 group->getTestContext(), testName.c_str(), testParams));
3669 }
3670 }
3671 }
3672 }
3673 }
3674 topGroup->addChild(paddingTypeGroup.release());
3675 }
3676 bottomGroup->addChild(topGroup.release());
3677 }
3678 buildGroup->addChild(bottomGroup.release());
3679 }
3680 sourceTypeGroup->addChild(buildGroup.release());
3681 }
3682 group->addChild(sourceTypeGroup.release());
3683 }
3684 }
3685
addVertexIndexFormatsTests(tcu::TestCaseGroup * group)3686 void addVertexIndexFormatsTests(tcu::TestCaseGroup *group)
3687 {
3688 struct ShaderSourceTypeData
3689 {
3690 ShaderSourceType shaderSourceType;
3691 ShaderSourcePipeline shaderSourcePipeline;
3692 const char *name;
3693 } shaderSourceTypes[] = {
3694 {SST_VERTEX_SHADER, SSP_GRAPHICS_PIPELINE, "vertex_shader"},
3695 {SST_TESSELATION_CONTROL_SHADER, SSP_GRAPHICS_PIPELINE, "tess_control_shader"},
3696 {SST_TESSELATION_EVALUATION_SHADER, SSP_GRAPHICS_PIPELINE, "tess_evaluation_shader"},
3697 {
3698 SST_GEOMETRY_SHADER,
3699 SSP_GRAPHICS_PIPELINE,
3700 "geometry_shader",
3701 },
3702 {
3703 SST_FRAGMENT_SHADER,
3704 SSP_GRAPHICS_PIPELINE,
3705 "fragment_shader",
3706 },
3707 {
3708 SST_COMPUTE_SHADER,
3709 SSP_COMPUTE_PIPELINE,
3710 "compute_shader",
3711 },
3712 {
3713 SST_RAY_GENERATION_SHADER,
3714 SSP_RAY_TRACING_PIPELINE,
3715 "rgen_shader",
3716 },
3717 {
3718 SST_INTERSECTION_SHADER,
3719 SSP_RAY_TRACING_PIPELINE,
3720 "isect_shader",
3721 },
3722 {
3723 SST_ANY_HIT_SHADER,
3724 SSP_RAY_TRACING_PIPELINE,
3725 "ahit_shader",
3726 },
3727 {
3728 SST_CLOSEST_HIT_SHADER,
3729 SSP_RAY_TRACING_PIPELINE,
3730 "chit_shader",
3731 },
3732 {
3733 SST_MISS_SHADER,
3734 SSP_RAY_TRACING_PIPELINE,
3735 "miss_shader",
3736 },
3737 {
3738 SST_CALLABLE_SHADER,
3739 SSP_RAY_TRACING_PIPELINE,
3740 "call_shader",
3741 },
3742 };
3743
3744 struct
3745 {
3746 vk::VkAccelerationStructureBuildTypeKHR buildType;
3747 const char *name;
3748 } buildTypes[] = {
3749 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
3750 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
3751 };
3752
3753 const VkFormat vertexFormats[] = {
3754 // Mandatory formats.
3755 VK_FORMAT_R32G32_SFLOAT,
3756 VK_FORMAT_R32G32B32_SFLOAT,
3757 VK_FORMAT_R16G16_SFLOAT,
3758 VK_FORMAT_R16G16B16A16_SFLOAT,
3759 VK_FORMAT_R16G16_SNORM,
3760 VK_FORMAT_R16G16B16A16_SNORM,
3761
3762 // Additional formats.
3763 VK_FORMAT_R8G8_SNORM,
3764 VK_FORMAT_R8G8B8_SNORM,
3765 VK_FORMAT_R8G8B8A8_SNORM,
3766 VK_FORMAT_R16G16B16_SNORM,
3767 VK_FORMAT_R16G16B16_SFLOAT,
3768 VK_FORMAT_R32G32B32A32_SFLOAT,
3769 VK_FORMAT_R64G64_SFLOAT,
3770 VK_FORMAT_R64G64B64_SFLOAT,
3771 VK_FORMAT_R64G64B64A64_SFLOAT,
3772 };
3773
3774 struct
3775 {
3776 VkIndexType indexType;
3777 const char *name;
3778 } indexFormats[] = {
3779 {VK_INDEX_TYPE_NONE_KHR, "index_none"},
3780 {VK_INDEX_TYPE_UINT16, "index_uint16"},
3781 {VK_INDEX_TYPE_UINT32, "index_uint32"},
3782 };
3783
3784 struct
3785 {
3786 bool padVertices;
3787 const char *name;
3788 } paddingType[] = {
3789 {false, "nopadding"},
3790 {true, "padded"},
3791 };
3792
3793 for (size_t shaderSourceNdx = 0; shaderSourceNdx < DE_LENGTH_OF_ARRAY(shaderSourceTypes); ++shaderSourceNdx)
3794 {
3795 de::MovePtr<tcu::TestCaseGroup> sourceTypeGroup(
3796 new tcu::TestCaseGroup(group->getTestContext(), shaderSourceTypes[shaderSourceNdx].name));
3797
3798 for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
3799 {
3800 de::MovePtr<tcu::TestCaseGroup> buildGroup(
3801 new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
3802
3803 for (size_t vertexFormatNdx = 0; vertexFormatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); ++vertexFormatNdx)
3804 {
3805 const auto format = vertexFormats[vertexFormatNdx];
3806 const auto formatName = getFormatSimpleName(format);
3807
3808 de::MovePtr<tcu::TestCaseGroup> vertexFormatGroup(
3809 new tcu::TestCaseGroup(group->getTestContext(), formatName.c_str()));
3810
3811 for (int paddingIdx = 0; paddingIdx < DE_LENGTH_OF_ARRAY(paddingType); ++paddingIdx)
3812 {
3813 de::MovePtr<tcu::TestCaseGroup> paddingGroup(
3814 new tcu::TestCaseGroup(group->getTestContext(), paddingType[paddingIdx].name));
3815
3816 for (size_t indexFormatNdx = 0; indexFormatNdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatNdx)
3817 {
3818 TestParams testParams{
3819 shaderSourceTypes[shaderSourceNdx].shaderSourceType,
3820 shaderSourceTypes[shaderSourceNdx].shaderSourcePipeline,
3821 buildTypes[buildTypeNdx].buildType,
3822 format,
3823 paddingType[paddingIdx].padVertices,
3824 indexFormats[indexFormatNdx].indexType,
3825 BottomTestType::TRIANGLES,
3826 InstanceCullFlags::NONE,
3827 false,
3828 false,
3829 false,
3830 TopTestType::IDENTICAL_INSTANCES,
3831 false,
3832 false,
3833 false,
3834 VkBuildAccelerationStructureFlagsKHR(0u),
3835 OT_NONE,
3836 OP_NONE,
3837 TEST_WIDTH,
3838 TEST_HEIGHT,
3839 0u,
3840 EmptyAccelerationStructureCase::NOT_EMPTY,
3841 };
3842 paddingGroup->addChild(new RayQueryASBasicTestCase(
3843 group->getTestContext(), indexFormats[indexFormatNdx].name, testParams));
3844 }
3845 vertexFormatGroup->addChild(paddingGroup.release());
3846 }
3847 buildGroup->addChild(vertexFormatGroup.release());
3848 }
3849 sourceTypeGroup->addChild(buildGroup.release());
3850 }
3851 group->addChild(sourceTypeGroup.release());
3852 }
3853 }
3854
addOperationTestsImpl(tcu::TestCaseGroup * group,const uint32_t workerThreads)3855 void addOperationTestsImpl(tcu::TestCaseGroup *group, const uint32_t workerThreads)
3856 {
3857 struct ShaderSourceTypeData
3858 {
3859 ShaderSourceType shaderSourceType;
3860 ShaderSourcePipeline shaderSourcePipeline;
3861 const char *name;
3862 } shaderSourceTypes[] = {
3863 {SST_VERTEX_SHADER, SSP_GRAPHICS_PIPELINE, "vertex_shader"},
3864 {SST_TESSELATION_CONTROL_SHADER, SSP_GRAPHICS_PIPELINE, "tess_control_shader"},
3865 {SST_TESSELATION_EVALUATION_SHADER, SSP_GRAPHICS_PIPELINE, "tess_evaluation_shader"},
3866 {
3867 SST_GEOMETRY_SHADER,
3868 SSP_GRAPHICS_PIPELINE,
3869 "geometry_shader",
3870 },
3871 {
3872 SST_FRAGMENT_SHADER,
3873 SSP_GRAPHICS_PIPELINE,
3874 "fragment_shader",
3875 },
3876 {
3877 SST_COMPUTE_SHADER,
3878 SSP_COMPUTE_PIPELINE,
3879 "compute_shader",
3880 },
3881 {
3882 SST_RAY_GENERATION_SHADER,
3883 SSP_RAY_TRACING_PIPELINE,
3884 "rgen_shader",
3885 },
3886 {
3887 SST_INTERSECTION_SHADER,
3888 SSP_RAY_TRACING_PIPELINE,
3889 "isect_shader",
3890 },
3891 {
3892 SST_ANY_HIT_SHADER,
3893 SSP_RAY_TRACING_PIPELINE,
3894 "ahit_shader",
3895 },
3896 {
3897 SST_CLOSEST_HIT_SHADER,
3898 SSP_RAY_TRACING_PIPELINE,
3899 "chit_shader",
3900 },
3901 {
3902 SST_MISS_SHADER,
3903 SSP_RAY_TRACING_PIPELINE,
3904 "miss_shader",
3905 },
3906 {
3907 SST_CALLABLE_SHADER,
3908 SSP_RAY_TRACING_PIPELINE,
3909 "call_shader",
3910 },
3911 };
3912
3913 struct
3914 {
3915 OperationType operationType;
3916 const char *name;
3917 } operationTypes[] = {
3918 {OP_COPY, "copy"},
3919 {OP_COMPACT, "compaction"},
3920 {OP_SERIALIZE, "serialization"},
3921 };
3922
3923 struct
3924 {
3925 vk::VkAccelerationStructureBuildTypeKHR buildType;
3926 const char *name;
3927 } buildTypes[] = {
3928 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
3929 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
3930 };
3931
3932 struct
3933 {
3934 OperationTarget operationTarget;
3935 const char *name;
3936 } operationTargets[] = {
3937 {OT_TOP_ACCELERATION, "top_acceleration_structure"},
3938 {OT_BOTTOM_ACCELERATION, "bottom_acceleration_structure"},
3939 };
3940
3941 struct
3942 {
3943 BottomTestType testType;
3944 const char *name;
3945 } bottomTestTypes[] = {
3946 {BottomTestType::TRIANGLES, "triangles"},
3947 {BottomTestType::AABBS, "aabbs"},
3948 };
3949
3950 for (size_t shaderSourceNdx = 0; shaderSourceNdx < DE_LENGTH_OF_ARRAY(shaderSourceTypes); ++shaderSourceNdx)
3951 {
3952 de::MovePtr<tcu::TestCaseGroup> sourceTypeGroup(
3953 new tcu::TestCaseGroup(group->getTestContext(), shaderSourceTypes[shaderSourceNdx].name));
3954
3955 for (size_t operationTypeNdx = 0; operationTypeNdx < DE_LENGTH_OF_ARRAY(operationTypes); ++operationTypeNdx)
3956 {
3957 if (workerThreads > 0)
3958 if (operationTypes[operationTypeNdx].operationType != OP_COPY &&
3959 operationTypes[operationTypeNdx].operationType != OP_SERIALIZE)
3960 continue;
3961
3962 de::MovePtr<tcu::TestCaseGroup> operationTypeGroup(
3963 new tcu::TestCaseGroup(group->getTestContext(), operationTypes[operationTypeNdx].name));
3964
3965 for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
3966 {
3967 if (workerThreads > 0 &&
3968 buildTypes[buildTypeNdx].buildType != VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR)
3969 continue;
3970
3971 de::MovePtr<tcu::TestCaseGroup> buildGroup(
3972 new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
3973
3974 for (size_t operationTargetNdx = 0; operationTargetNdx < DE_LENGTH_OF_ARRAY(operationTargets);
3975 ++operationTargetNdx)
3976 {
3977 de::MovePtr<tcu::TestCaseGroup> operationTargetGroup(
3978 new tcu::TestCaseGroup(group->getTestContext(), operationTargets[operationTargetNdx].name));
3979
3980 for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++testTypeNdx)
3981 {
3982 TopTestType topTest =
3983 (operationTargets[operationTargetNdx].operationTarget == OT_TOP_ACCELERATION) ?
3984 TopTestType::DIFFERENT_INSTANCES :
3985 TopTestType::IDENTICAL_INSTANCES;
3986
3987 TestParams testParams{
3988 shaderSourceTypes[shaderSourceNdx].shaderSourceType,
3989 shaderSourceTypes[shaderSourceNdx].shaderSourcePipeline,
3990 buildTypes[buildTypeNdx].buildType,
3991 VK_FORMAT_R32G32B32_SFLOAT,
3992 false,
3993 VK_INDEX_TYPE_NONE_KHR,
3994 bottomTestTypes[testTypeNdx].testType,
3995 InstanceCullFlags::NONE,
3996 false,
3997 false,
3998 false,
3999 topTest,
4000 false,
4001 false,
4002 false,
4003 VkBuildAccelerationStructureFlagsKHR(0u),
4004 operationTargets[operationTargetNdx].operationTarget,
4005 operationTypes[operationTypeNdx].operationType,
4006 TEST_WIDTH,
4007 TEST_HEIGHT,
4008 workerThreads,
4009 EmptyAccelerationStructureCase::NOT_EMPTY,
4010 };
4011 operationTargetGroup->addChild(new RayQueryASBasicTestCase(
4012 group->getTestContext(), bottomTestTypes[testTypeNdx].name, testParams));
4013 }
4014 buildGroup->addChild(operationTargetGroup.release());
4015 }
4016 operationTypeGroup->addChild(buildGroup.release());
4017 }
4018 sourceTypeGroup->addChild(operationTypeGroup.release());
4019 }
4020 group->addChild(sourceTypeGroup.release());
4021 }
4022 }
4023
addOperationTests(tcu::TestCaseGroup * group)4024 void addOperationTests(tcu::TestCaseGroup *group)
4025 {
4026 addOperationTestsImpl(group, 0);
4027 }
4028
addHostThreadingOperationTests(tcu::TestCaseGroup * group)4029 void addHostThreadingOperationTests(tcu::TestCaseGroup *group)
4030 {
4031 const uint32_t threads[] = {1, 2, 3, 4, 8, std::numeric_limits<uint32_t>::max()};
4032
4033 for (size_t threadsNdx = 0; threadsNdx < DE_LENGTH_OF_ARRAY(threads); ++threadsNdx)
4034 {
4035 const std::string groupName =
4036 threads[threadsNdx] != std::numeric_limits<uint32_t>::max() ? de::toString(threads[threadsNdx]) : "max";
4037
4038 de::MovePtr<tcu::TestCaseGroup> threadGroup(new tcu::TestCaseGroup(group->getTestContext(), groupName.c_str()));
4039
4040 addOperationTestsImpl(threadGroup.get(), threads[threadsNdx]);
4041
4042 group->addChild(threadGroup.release());
4043 }
4044 }
4045
addFuncArgTests(tcu::TestCaseGroup * group)4046 void addFuncArgTests(tcu::TestCaseGroup *group)
4047 {
4048 const struct
4049 {
4050 vk::VkAccelerationStructureBuildTypeKHR buildType;
4051 const char *name;
4052 } buildTypes[] = {
4053 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
4054 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
4055 };
4056
4057 auto &ctx = group->getTestContext();
4058
4059 for (int buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
4060 {
4061 TestParams testParams{
4062 SST_COMPUTE_SHADER,
4063 SSP_COMPUTE_PIPELINE,
4064 buildTypes[buildTypeNdx].buildType,
4065 VK_FORMAT_R32G32B32_SFLOAT,
4066 false,
4067 VK_INDEX_TYPE_NONE_KHR,
4068 BottomTestType::TRIANGLES,
4069 InstanceCullFlags::NONE,
4070 false,
4071 false,
4072 false,
4073 TopTestType::IDENTICAL_INSTANCES,
4074 false,
4075 false,
4076 false,
4077 VkBuildAccelerationStructureFlagsKHR(0u),
4078 OT_NONE,
4079 OP_NONE,
4080 TEST_WIDTH,
4081 TEST_HEIGHT,
4082 0u,
4083 EmptyAccelerationStructureCase::NOT_EMPTY,
4084 };
4085
4086 group->addChild(new RayQueryASFuncArgTestCase(ctx, buildTypes[buildTypeNdx].name, testParams));
4087 }
4088 }
4089
addInstanceTriangleCullingTests(tcu::TestCaseGroup * group)4090 void addInstanceTriangleCullingTests(tcu::TestCaseGroup *group)
4091 {
4092 const struct
4093 {
4094 ShaderSourceType shaderSourceType;
4095 ShaderSourcePipeline shaderSourcePipeline;
4096 std::string name;
4097 } shaderSourceTypes[] = {
4098 {SST_VERTEX_SHADER, SSP_GRAPHICS_PIPELINE, "vertex_shader"},
4099 {SST_TESSELATION_CONTROL_SHADER, SSP_GRAPHICS_PIPELINE, "tess_control_shader"},
4100 {SST_TESSELATION_EVALUATION_SHADER, SSP_GRAPHICS_PIPELINE, "tess_evaluation_shader"},
4101 {
4102 SST_GEOMETRY_SHADER,
4103 SSP_GRAPHICS_PIPELINE,
4104 "geometry_shader",
4105 },
4106 {
4107 SST_FRAGMENT_SHADER,
4108 SSP_GRAPHICS_PIPELINE,
4109 "fragment_shader",
4110 },
4111 {
4112 SST_COMPUTE_SHADER,
4113 SSP_COMPUTE_PIPELINE,
4114 "compute_shader",
4115 },
4116 {
4117 SST_RAY_GENERATION_SHADER,
4118 SSP_RAY_TRACING_PIPELINE,
4119 "rgen_shader",
4120 },
4121 {
4122 SST_INTERSECTION_SHADER,
4123 SSP_RAY_TRACING_PIPELINE,
4124 "isect_shader",
4125 },
4126 {
4127 SST_ANY_HIT_SHADER,
4128 SSP_RAY_TRACING_PIPELINE,
4129 "ahit_shader",
4130 },
4131 {
4132 SST_CLOSEST_HIT_SHADER,
4133 SSP_RAY_TRACING_PIPELINE,
4134 "chit_shader",
4135 },
4136 {
4137 SST_MISS_SHADER,
4138 SSP_RAY_TRACING_PIPELINE,
4139 "miss_shader",
4140 },
4141 {
4142 SST_CALLABLE_SHADER,
4143 SSP_RAY_TRACING_PIPELINE,
4144 "call_shader",
4145 },
4146 };
4147
4148 const struct
4149 {
4150 InstanceCullFlags cullFlags;
4151 std::string name;
4152 } cullFlags[] = {
4153 {InstanceCullFlags::NONE, "noflags"},
4154 {InstanceCullFlags::COUNTERCLOCKWISE, "ccw"},
4155 {InstanceCullFlags::CULL_DISABLE, "nocull"},
4156 {InstanceCullFlags::ALL, "ccw_nocull"},
4157 };
4158
4159 const struct
4160 {
4161 TopTestType topType;
4162 std::string name;
4163 } topType[] = {
4164 {TopTestType::DIFFERENT_INSTANCES, "transformed"}, // Each instance has its own transformation matrix.
4165 {TopTestType::IDENTICAL_INSTANCES, "notransform"}, // "Identical" instances, different geometries.
4166 };
4167
4168 const struct
4169 {
4170 vk::VkAccelerationStructureBuildTypeKHR buildType;
4171 std::string name;
4172 } buildTypes[] = {
4173 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
4174 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
4175 };
4176
4177 const struct
4178 {
4179 VkIndexType indexType;
4180 std::string name;
4181 } indexFormats[] = {
4182 {VK_INDEX_TYPE_NONE_KHR, "index_none"},
4183 {VK_INDEX_TYPE_UINT16, "index_uint16"},
4184 {VK_INDEX_TYPE_UINT32, "index_uint32"},
4185 };
4186
4187 auto &ctx = group->getTestContext();
4188
4189 for (int shaderSourceIdx = 0; shaderSourceIdx < DE_LENGTH_OF_ARRAY(shaderSourceTypes); ++shaderSourceIdx)
4190 {
4191 de::MovePtr<tcu::TestCaseGroup> shaderSourceGroup(
4192 new tcu::TestCaseGroup(ctx, shaderSourceTypes[shaderSourceIdx].name.c_str()));
4193
4194 for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
4195 {
4196 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
4197 new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
4198
4199 for (int indexFormatIdx = 0; indexFormatIdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatIdx)
4200 {
4201 de::MovePtr<tcu::TestCaseGroup> indexTypeGroup(
4202 new tcu::TestCaseGroup(ctx, indexFormats[indexFormatIdx].name.c_str()));
4203
4204 for (int topTypeIdx = 0; topTypeIdx < DE_LENGTH_OF_ARRAY(topType); ++topTypeIdx)
4205 {
4206 for (int cullFlagsIdx = 0; cullFlagsIdx < DE_LENGTH_OF_ARRAY(cullFlags); ++cullFlagsIdx)
4207 {
4208 const std::string testName = topType[topTypeIdx].name + "_" + cullFlags[cullFlagsIdx].name;
4209
4210 TestParams testParams{
4211 shaderSourceTypes[shaderSourceIdx].shaderSourceType,
4212 shaderSourceTypes[shaderSourceIdx].shaderSourcePipeline,
4213 buildTypes[buildTypeIdx].buildType,
4214 VK_FORMAT_R32G32B32_SFLOAT,
4215 false,
4216 indexFormats[indexFormatIdx].indexType,
4217 BottomTestType::TRIANGLES,
4218 cullFlags[cullFlagsIdx].cullFlags,
4219 false,
4220 false,
4221 false,
4222 topType[topTypeIdx].topType,
4223 false,
4224 false,
4225 false,
4226 VkBuildAccelerationStructureFlagsKHR(0u),
4227 OT_NONE,
4228 OP_NONE,
4229 TEST_WIDTH,
4230 TEST_HEIGHT,
4231 0u,
4232 EmptyAccelerationStructureCase::NOT_EMPTY,
4233 };
4234 indexTypeGroup->addChild(new RayQueryASBasicTestCase(ctx, testName.c_str(), testParams));
4235 }
4236 }
4237 buildTypeGroup->addChild(indexTypeGroup.release());
4238 }
4239 shaderSourceGroup->addChild(buildTypeGroup.release());
4240 }
4241 group->addChild(shaderSourceGroup.release());
4242 }
4243 }
4244
addInstanceUpdateTests(tcu::TestCaseGroup * group)4245 void addInstanceUpdateTests(tcu::TestCaseGroup *group)
4246 {
4247 const struct
4248 {
4249 vk::VkAccelerationStructureBuildTypeKHR buildType;
4250 std::string name;
4251 } buildTypes[] = {
4252 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
4253 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
4254 };
4255
4256 struct
4257 {
4258 OperationType operationType;
4259 const char *name;
4260 } operationTypes[] = {
4261 {OP_UPDATE, "update"},
4262 {OP_UPDATE_IN_PLACE, "update_in_place"},
4263 };
4264
4265 auto &ctx = group->getTestContext();
4266
4267 for (int buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
4268 {
4269 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
4270 new tcu::TestCaseGroup(ctx, buildTypes[buildTypeNdx].name.c_str()));
4271
4272 for (int operationTypesIdx = 0; operationTypesIdx < DE_LENGTH_OF_ARRAY(operationTypes); ++operationTypesIdx)
4273 {
4274 TestParams testParams{
4275 SST_COMPUTE_SHADER,
4276 SSP_COMPUTE_PIPELINE,
4277 buildTypes[buildTypeNdx].buildType,
4278 VK_FORMAT_R32G32B32_SFLOAT,
4279 false,
4280 VK_INDEX_TYPE_NONE_KHR,
4281 BottomTestType::TRIANGLES,
4282 InstanceCullFlags::NONE,
4283 false,
4284 false,
4285 false,
4286 TopTestType::IDENTICAL_INSTANCES,
4287 false,
4288 false,
4289 false,
4290 VkBuildAccelerationStructureFlagsKHR(0u),
4291 OT_NONE,
4292 OP_NONE,
4293 TEST_WIDTH,
4294 TEST_HEIGHT,
4295 0u,
4296 EmptyAccelerationStructureCase::NOT_EMPTY,
4297 };
4298
4299 buildTypeGroup->addChild(
4300 new RayQueryASFuncArgTestCase(ctx, operationTypes[operationTypesIdx].name, testParams));
4301 }
4302 group->addChild(buildTypeGroup.release());
4303 }
4304 }
4305
addDynamicIndexingTests(tcu::TestCaseGroup * group)4306 void addDynamicIndexingTests(tcu::TestCaseGroup *group)
4307 {
4308 auto &ctx = group->getTestContext();
4309 group->addChild(new RayQueryASDynamicIndexingTestCase(ctx, "dynamic_indexing"));
4310 }
4311
addEmptyAccelerationStructureTests(tcu::TestCaseGroup * group)4312 void addEmptyAccelerationStructureTests(tcu::TestCaseGroup *group)
4313 {
4314 const struct
4315 {
4316 ShaderSourceType shaderSourceType;
4317 ShaderSourcePipeline shaderSourcePipeline;
4318 std::string name;
4319 } shaderSourceTypes[] = {
4320 {SST_VERTEX_SHADER, SSP_GRAPHICS_PIPELINE, "vertex_shader"},
4321 {SST_TESSELATION_CONTROL_SHADER, SSP_GRAPHICS_PIPELINE, "tess_control_shader"},
4322 {SST_TESSELATION_EVALUATION_SHADER, SSP_GRAPHICS_PIPELINE, "tess_evaluation_shader"},
4323 {
4324 SST_GEOMETRY_SHADER,
4325 SSP_GRAPHICS_PIPELINE,
4326 "geometry_shader",
4327 },
4328 {
4329 SST_FRAGMENT_SHADER,
4330 SSP_GRAPHICS_PIPELINE,
4331 "fragment_shader",
4332 },
4333 {
4334 SST_COMPUTE_SHADER,
4335 SSP_COMPUTE_PIPELINE,
4336 "compute_shader",
4337 },
4338 {
4339 SST_RAY_GENERATION_SHADER,
4340 SSP_RAY_TRACING_PIPELINE,
4341 "rgen_shader",
4342 },
4343 {
4344 SST_INTERSECTION_SHADER,
4345 SSP_RAY_TRACING_PIPELINE,
4346 "isect_shader",
4347 },
4348 {
4349 SST_ANY_HIT_SHADER,
4350 SSP_RAY_TRACING_PIPELINE,
4351 "ahit_shader",
4352 },
4353 {
4354 SST_CLOSEST_HIT_SHADER,
4355 SSP_RAY_TRACING_PIPELINE,
4356 "chit_shader",
4357 },
4358 {
4359 SST_MISS_SHADER,
4360 SSP_RAY_TRACING_PIPELINE,
4361 "miss_shader",
4362 },
4363 {
4364 SST_CALLABLE_SHADER,
4365 SSP_RAY_TRACING_PIPELINE,
4366 "call_shader",
4367 },
4368 };
4369
4370 const struct
4371 {
4372 vk::VkAccelerationStructureBuildTypeKHR buildType;
4373 std::string name;
4374 } buildTypes[] = {
4375 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
4376 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
4377 };
4378
4379 const struct
4380 {
4381 VkIndexType indexType;
4382 std::string name;
4383 } indexFormats[] = {
4384 {VK_INDEX_TYPE_NONE_KHR, "index_none"},
4385 {VK_INDEX_TYPE_UINT16, "index_uint16"},
4386 {VK_INDEX_TYPE_UINT32, "index_uint32"},
4387 };
4388
4389 const struct
4390 {
4391 EmptyAccelerationStructureCase emptyASCase;
4392 std::string name;
4393 } emptyCases[] = {
4394 {EmptyAccelerationStructureCase::INACTIVE_TRIANGLES, "inactive_triangles"},
4395 {EmptyAccelerationStructureCase::INACTIVE_INSTANCES, "inactive_instances"},
4396 {EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM, "no_geometries_bottom"},
4397 {EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP, "no_primitives_top"},
4398 {EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM, "no_primitives_bottom"},
4399 };
4400
4401 auto &ctx = group->getTestContext();
4402
4403 for (size_t shaderSourceNdx = 0; shaderSourceNdx < DE_LENGTH_OF_ARRAY(shaderSourceTypes); ++shaderSourceNdx)
4404 {
4405 de::MovePtr<tcu::TestCaseGroup> sourceTypeGroup(
4406 new tcu::TestCaseGroup(ctx, shaderSourceTypes[shaderSourceNdx].name.c_str()));
4407
4408 for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
4409 {
4410 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
4411 new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
4412
4413 for (int indexFormatIdx = 0; indexFormatIdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatIdx)
4414 {
4415 de::MovePtr<tcu::TestCaseGroup> indexTypeGroup(
4416 new tcu::TestCaseGroup(ctx, indexFormats[indexFormatIdx].name.c_str()));
4417
4418 for (int emptyCaseIdx = 0; emptyCaseIdx < DE_LENGTH_OF_ARRAY(emptyCases); ++emptyCaseIdx)
4419 {
4420 TestParams testParams{
4421 shaderSourceTypes[shaderSourceNdx].shaderSourceType,
4422 shaderSourceTypes[shaderSourceNdx].shaderSourcePipeline,
4423 buildTypes[buildTypeIdx].buildType,
4424 VK_FORMAT_R32G32B32_SFLOAT,
4425 false,
4426 indexFormats[indexFormatIdx].indexType,
4427 BottomTestType::TRIANGLES,
4428 InstanceCullFlags::NONE,
4429 false,
4430 false,
4431 false,
4432 TopTestType::IDENTICAL_INSTANCES,
4433 false,
4434 false,
4435 false,
4436 VkBuildAccelerationStructureFlagsKHR(0u),
4437 OT_NONE,
4438 OP_NONE,
4439 TEST_WIDTH,
4440 TEST_HEIGHT,
4441 0u,
4442 emptyCases[emptyCaseIdx].emptyASCase,
4443 };
4444 indexTypeGroup->addChild(
4445 new RayQueryASBasicTestCase(ctx, emptyCases[emptyCaseIdx].name.c_str(), testParams));
4446 }
4447 buildTypeGroup->addChild(indexTypeGroup.release());
4448 }
4449 sourceTypeGroup->addChild(buildTypeGroup.release());
4450 }
4451 group->addChild(sourceTypeGroup.release());
4452 }
4453 }
4454
createAccelerationStructuresTests(tcu::TestContext & testCtx)4455 tcu::TestCaseGroup *createAccelerationStructuresTests(tcu::TestContext &testCtx)
4456 {
4457 // Acceleration structure tests using rayQuery feature
4458 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "acceleration_structures"));
4459
4460 // Test building AS with different build types, build flags and geometries/instances using arrays or arrays of pointers
4461 addTestGroup(group.get(), "flags", addBasicBuildingTests);
4462 // Test building AS with different vertex and index formats
4463 addTestGroup(group.get(), "format", addVertexIndexFormatsTests);
4464 // Test copying, compaction and serialization of AS
4465 addTestGroup(group.get(), "operations", addOperationTests);
4466 // Test host threading operations
4467 addTestGroup(group.get(), "host_threading", addHostThreadingOperationTests);
4468 // Test using AS as function argument using both pointers and bare values
4469 addTestGroup(group.get(), "function_argument", addFuncArgTests);
4470 // Test building AS with counterclockwise triangles and/or disabling face culling
4471 addTestGroup(group.get(), "instance_triangle_culling", addInstanceTriangleCullingTests);
4472 // Test updating instance index using both in-place and separate src/dst acceleration structures
4473 addTestGroup(group.get(), "instance_update", addInstanceUpdateTests);
4474 // Exercise dynamic indexing of acceleration structures
4475 addTestGroup(group.get(), "dynamic_indexing", addDynamicIndexingTests);
4476 // Test building empty acceleration structures using different methods
4477 addTestGroup(group.get(), "empty", addEmptyAccelerationStructureTests);
4478
4479 return group.release();
4480 }
4481
4482 } // namespace RayQuery
4483
4484 } // namespace vkt
4485