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 Ray Tracing Shader Binding Table tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktRayTracingShaderBindingTableTests.hpp"
25
26 #include "vkDefs.hpp"
27
28 #include "vktTestCase.hpp"
29 #include "vktTestGroupUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkBarrierUtil.hpp"
34 #include "vkBufferWithMemory.hpp"
35 #include "vkImageWithMemory.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "deRandom.hpp"
39 #include "tcuTexture.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include "tcuTestLog.hpp"
42 #include "tcuImageCompare.hpp"
43
44 #include "vkRayTracingUtil.hpp"
45
46 namespace vkt
47 {
48 namespace RayTracing
49 {
50 namespace
51 {
52 using namespace vk;
53 using namespace vkt;
54
55 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR
56 | VK_SHADER_STAGE_ANY_HIT_BIT_KHR
57 | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
58 | VK_SHADER_STAGE_MISS_BIT_KHR
59 | VK_SHADER_STAGE_INTERSECTION_BIT_KHR
60 | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
61
62 enum ShaderTestType
63 {
64 STT_HIT = 0,
65 STT_MISS = 1,
66 STT_CALL = 2,
67 STT_COUNT = 3
68 };
69
70 const deUint32 CHECKERBOARD_WIDTH = 8;
71 const deUint32 CHECKERBOARD_HEIGHT = 8;
72 const deUint32 HIT_GEOMETRY_COUNT = 3;
73 const deUint32 HIT_INSTANCE_COUNT = 1 + CHECKERBOARD_WIDTH * CHECKERBOARD_HEIGHT / ( 2 * HIT_GEOMETRY_COUNT );
74
75 const deUint32 MAX_SBT_RECORD_OFFSET = 3;
76 const deUint32 MAX_HIT_SBT_RECORD_STRIDE = HIT_GEOMETRY_COUNT + 1;
77 const deUint32 SBT_RANDOM_SEED = 1410;
78
79 struct TestParams;
80
81 class TestConfiguration
82 {
83 public:
84 virtual std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures (Context& context,
85 TestParams& testParams) = 0;
86 virtual de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure (Context& context,
87 TestParams& testParams,
88 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures) = 0;
89 virtual de::MovePtr<BufferWithMemory> initUniformBuffer (Context& context,
90 TestParams& testParams) = 0;
91 virtual void initRayTracingShaders (de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
92 Context& context,
93 TestParams& testParams) = 0;
94 virtual void initShaderBindingTables (de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
95 Context& context,
96 TestParams& testParams,
97 VkPipeline pipeline,
98 deUint32 shaderGroupHandleSize,
99 deUint32 shaderGroupBaseAlignment,
100 de::MovePtr<BufferWithMemory>& raygenShaderBindingTable,
101 de::MovePtr<BufferWithMemory>& hitShaderBindingTable,
102 de::MovePtr<BufferWithMemory>& missShaderBindingTable,
103 de::MovePtr<BufferWithMemory>& callableShaderBindingTable,
104 VkStridedDeviceAddressRegionKHR& raygenShaderBindingTableRegion,
105 VkStridedDeviceAddressRegionKHR& hitShaderBindingTableRegion,
106 VkStridedDeviceAddressRegionKHR& missShaderBindingTableRegion,
107 VkStridedDeviceAddressRegionKHR& callableShaderBindingTableRegion) = 0;
108 virtual bool verifyImage (BufferWithMemory* resultBuffer,
109 Context& context,
110 TestParams& testParams) = 0;
111 virtual VkFormat getResultImageFormat () = 0;
112 virtual size_t getResultImageFormatSize () = 0;
113 virtual VkClearValue getClearValue () = 0;
114 };
115
116 struct TestParams
117 {
118 deUint32 width;
119 deUint32 height;
120 ShaderTestType shaderTestType;
121 deUint32 sbtOffset;
122 bool shaderRecordPresent;
123 deUint32 sbtRecordOffset;
124 deUint32 sbtRecordOffsetPassedToTraceRay;
125 deUint32 sbtRecordStride;
126 deUint32 sbtRecordStridePassedToTraceRay;
127 de::SharedPtr<TestConfiguration> testConfiguration;
128
129 };
130
getShaderCounts()131 std::vector<deUint32> getShaderCounts ()
132 {
133 std::vector<deUint32> shaderCount(STT_COUNT);
134 shaderCount[STT_HIT] = HIT_INSTANCE_COUNT + HIT_GEOMETRY_COUNT * MAX_HIT_SBT_RECORD_STRIDE + MAX_SBT_RECORD_OFFSET + 1;
135 shaderCount[STT_MISS] = MAX_SBT_RECORD_OFFSET + HIT_INSTANCE_COUNT + 1;
136 shaderCount[STT_CALL] = MAX_SBT_RECORD_OFFSET + HIT_INSTANCE_COUNT + 1;
137 return shaderCount;
138 }
139
getShaderGroupHandleSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)140 deUint32 getShaderGroupHandleSize (const InstanceInterface& vki,
141 const VkPhysicalDevice physicalDevice)
142 {
143 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
144
145 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
146 return rayTracingPropertiesKHR->getShaderGroupHandleSize();
147 }
148
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)149 deUint32 getShaderGroupBaseAlignment (const InstanceInterface& vki,
150 const VkPhysicalDevice physicalDevice)
151 {
152 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
153
154 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
155 return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
156 }
157
makeImageCreateInfo(deUint32 width,deUint32 height,VkFormat format)158 VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, VkFormat format)
159 {
160 const VkImageCreateInfo imageCreateInfo =
161 {
162 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
163 DE_NULL, // const void* pNext;
164 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
165 VK_IMAGE_TYPE_2D, // VkImageType imageType;
166 format, // VkFormat format;
167 makeExtent3D(width, height, 1), // VkExtent3D extent;
168 1u, // deUint32 mipLevels;
169 1u, // deUint32 arrayLayers;
170 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
171 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
172 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
173 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
174 0u, // deUint32 queueFamilyIndexCount;
175 DE_NULL, // const deUint32* pQueueFamilyIndices;
176 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
177 };
178
179 return imageCreateInfo;
180 }
181
182 class CheckerboardConfiguration : public TestConfiguration
183 {
184 public:
185 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures (Context& context,
186 TestParams& testParams) override;
187 de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure (Context& context,
188 TestParams& testParams,
189 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures) override;
190 de::MovePtr<BufferWithMemory> initUniformBuffer (Context& context,
191 TestParams& testParams) override;
192 void initRayTracingShaders (de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
193 Context& context,
194 TestParams& testParams) override;
195 void initShaderBindingTables (de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
196 Context& context,
197 TestParams& testParams,
198 VkPipeline pipeline,
199 deUint32 shaderGroupHandleSize,
200 deUint32 shaderGroupBaseAlignment,
201 de::MovePtr<BufferWithMemory>& raygenShaderBindingTable,
202 de::MovePtr<BufferWithMemory>& hitShaderBindingTable,
203 de::MovePtr<BufferWithMemory>& missShaderBindingTable,
204 de::MovePtr<BufferWithMemory>& callableShaderBindingTable,
205 VkStridedDeviceAddressRegionKHR& raygenShaderBindingTableRegion,
206 VkStridedDeviceAddressRegionKHR& hitShaderBindingTableRegion,
207 VkStridedDeviceAddressRegionKHR& missShaderBindingTableRegion,
208 VkStridedDeviceAddressRegionKHR& callableShaderBindingTableRegion) override;
209 bool verifyImage (BufferWithMemory* resultBuffer,
210 Context& context,
211 TestParams& testParams) override;
212 VkFormat getResultImageFormat () override;
213 size_t getResultImageFormatSize () override;
214 VkClearValue getClearValue () override;
215 };
216
initBottomAccelerationStructures(Context & context,TestParams & testParams)217 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > CheckerboardConfiguration::initBottomAccelerationStructures (Context& context,
218 TestParams& testParams)
219 {
220 DE_UNREF(context);
221
222 std::vector<tcu::Vec3> corners;
223 for (deUint32 y = 0; y < testParams.height; ++y)
224 for (deUint32 x = 0; x < testParams.width; ++x)
225 {
226 if (((x + y) % 2) == 0)
227 continue;
228 corners.push_back(tcu::Vec3((float)x, (float)y, 0.0f));
229 }
230
231 de::Random rnd(SBT_RANDOM_SEED);
232 rnd.shuffle(begin(corners), end(corners));
233
234 tcu::Vec3 v0(0.0, 1.0, 0.0);
235 tcu::Vec3 v1(0.0, 0.0, 0.0);
236 tcu::Vec3 v2(1.0, 1.0, 0.0);
237 tcu::Vec3 v3(1.0, 0.0, 0.0);
238 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > result;
239
240 for (size_t cornerNdx = 0; cornerNdx < corners.size(); cornerNdx += HIT_GEOMETRY_COUNT)
241 {
242 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
243 size_t geometryCount = std::min(corners.size() - cornerNdx, size_t(HIT_GEOMETRY_COUNT));
244 bottomLevelAccelerationStructure->setGeometryCount(geometryCount);
245 for (size_t idx = cornerNdx; idx < cornerNdx + geometryCount; ++idx)
246 {
247 de::SharedPtr<RaytracedGeometryBase> geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
248 geometry->addVertex(corners[idx] + v0);
249 geometry->addVertex(corners[idx] + v1);
250 geometry->addVertex(corners[idx] + v2);
251 geometry->addVertex(corners[idx] + v2);
252 geometry->addVertex(corners[idx] + v1);
253 geometry->addVertex(corners[idx] + v3);
254 bottomLevelAccelerationStructure->addGeometry(geometry);
255 }
256 result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
257 }
258 return result;
259 }
260
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)261 de::MovePtr<TopLevelAccelerationStructure> CheckerboardConfiguration::initTopAccelerationStructure (Context& context,
262 TestParams& testParams,
263 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures)
264 {
265 DE_UNREF(context);
266 DE_UNREF(testParams);
267
268 de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
269 deUint32 instanceCount = deUint32(bottomLevelAccelerationStructures.size());
270 result->setInstanceCount(instanceCount);
271
272 VkTransformMatrixKHR identityMatrix = { { { 1.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f, 0.0f } } };
273 for (deUint32 i = 0; i < instanceCount; ++i)
274 result->addInstance(bottomLevelAccelerationStructures[i], identityMatrix, 0u, 0xFF, (testParams.shaderTestType == STT_MISS) ? 0 : i);
275
276 return result;
277 }
278
initUniformBuffer(Context & context,TestParams & testParams)279 de::MovePtr<BufferWithMemory> CheckerboardConfiguration::initUniformBuffer (Context& context,
280 TestParams& testParams)
281 {
282 const DeviceInterface& vkd = context.getDeviceInterface();
283 const VkDevice device = context.getDevice();
284 Allocator& allocator = context.getDefaultAllocator();
285
286 const VkBufferCreateInfo uniformBufferCreateInfo = makeBufferCreateInfo(sizeof(tcu::UVec4), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
287 de::MovePtr<BufferWithMemory> uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
288 tcu::UVec4 uniformValue; // x = sbtRecordOffset, y = sbtRecordStride, z = missIndex
289 switch (testParams.shaderTestType)
290 {
291 case STT_HIT:
292 {
293 uniformValue = tcu::UVec4(testParams.sbtRecordOffsetPassedToTraceRay, testParams.sbtRecordStride, 0, 0);
294 break;
295 }
296 case STT_MISS:
297 {
298 uniformValue = tcu::UVec4(0, 0, testParams.sbtRecordOffsetPassedToTraceRay, 0);
299 break;
300 }
301 case STT_CALL:
302 {
303 uniformValue = tcu::UVec4(testParams.sbtRecordOffsetPassedToTraceRay, testParams.sbtRecordStride, 0, 0);
304 break;
305 }
306 default:
307 TCU_THROW(InternalError, "Wrong shader test type");
308 }
309 deMemcpy(uniformBuffer->getAllocation().getHostPtr(), &uniformValue, sizeof(tcu::UVec4));
310 flushMappedMemoryRange(vkd, device, uniformBuffer->getAllocation().getMemory(), uniformBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
311
312 return uniformBuffer;
313 }
314
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams)315 void CheckerboardConfiguration::initRayTracingShaders (de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
316 Context& context,
317 TestParams& testParams)
318 {
319 const DeviceInterface& vkd = context.getDeviceInterface();
320 const VkDevice device = context.getDevice();
321
322 std::vector<deUint32> shaderCount = getShaderCounts();
323
324 switch (testParams.shaderTestType)
325 {
326 case STT_HIT:
327 {
328 if (testParams.shaderRecordPresent)
329 {
330 // shaders: rgen, chit_shaderRecord (N times), miss_0
331 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
332 for (deUint32 idx = 0; idx < shaderCount[STT_HIT]; ++idx)
333 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("chit_shaderRecord"), 0), 1+idx);
334 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("miss_0"), 0), 1 + shaderCount[STT_HIT]);
335 }
336 else
337 {
338 // shaders: rgen, chit_0 .. chit_N, miss_0
339 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
340 for (deUint32 idx = 0; idx < shaderCount[STT_HIT]; ++idx)
341 {
342 std::stringstream csname;
343 csname << "chit_" << idx;
344 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get(csname.str()), 0), 1 + idx);
345 }
346 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("miss_0"), 0), 1 + shaderCount[STT_HIT]);
347 }
348 rayTracingPipeline->setMaxPayloadSize(16u);
349 break;
350 }
351 case STT_MISS:
352 {
353 if (testParams.shaderRecordPresent)
354 {
355 // shaders: rgen, chit_0, miss_shaderRecord ( N times )
356 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
357 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("chit_0"), 0), 1);
358 for (deUint32 idx = 0; idx < shaderCount[STT_MISS]; ++idx)
359 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("miss_shaderRecord"), 0), 2 + idx);
360 }
361 else
362 {
363 // shaders: rgen, chit_0, miss_0 .. miss_N
364 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
365 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("chit_0"), 0), 1);
366 for (deUint32 idx = 0; idx < shaderCount[STT_MISS]; ++idx)
367 {
368 std::stringstream csname;
369 csname << "miss_" << idx;
370 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get(csname.str()), 0), 2 + idx);
371 }
372 }
373 rayTracingPipeline->setMaxPayloadSize(16u);
374 break;
375 }
376 case STT_CALL:
377 {
378 if (testParams.shaderRecordPresent)
379 {
380 // shaders: rgen, chit_call_0 .. chit_call_N, miss_0, call_shaderRecord ( N times )
381 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
382 for (deUint32 idx = 0; idx < shaderCount[STT_CALL]; ++idx)
383 {
384 std::stringstream csname;
385 csname << "chit_call_" << idx;
386 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get(csname.str()), 0), 1 + idx);
387 }
388 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("miss_0"), 0), 1 + shaderCount[STT_CALL]);
389 for (deUint32 idx = 0; idx < shaderCount[STT_CALL]; ++idx)
390 rayTracingPipeline->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("call_shaderRecord"), 0), 2 + shaderCount[STT_CALL] + idx);
391 }
392 else
393 {
394 // shaders: rgen, chit_call_0 .. chit_call_N, miss_0, call_0 .. call_N
395 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
396 for (deUint32 idx = 0; idx < shaderCount[STT_CALL]; ++idx)
397 {
398 std::stringstream csname;
399 csname << "chit_call_" << idx;
400 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get(csname.str()), 0), 1 + idx);
401 }
402 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("miss_0"), 0), 1 + shaderCount[STT_CALL]);
403 for (deUint32 idx = 0; idx < shaderCount[STT_CALL]; ++idx)
404 {
405 std::stringstream csname;
406 csname << "call_" << idx;
407 rayTracingPipeline->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get(csname.str()), 0), 2 + shaderCount[STT_CALL] + idx);
408 }
409 }
410 rayTracingPipeline->setMaxPayloadSize(16u);
411 break;
412 }
413 default:
414 TCU_THROW(InternalError, "Wrong shader test type");
415 }
416 }
417
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams,VkPipeline pipeline,deUint32 shaderGroupHandleSize,deUint32 shaderGroupBaseAlignment,de::MovePtr<BufferWithMemory> & raygenShaderBindingTable,de::MovePtr<BufferWithMemory> & hitShaderBindingTable,de::MovePtr<BufferWithMemory> & missShaderBindingTable,de::MovePtr<BufferWithMemory> & callableShaderBindingTable,VkStridedDeviceAddressRegionKHR & raygenShaderBindingTableRegion,VkStridedDeviceAddressRegionKHR & hitShaderBindingTableRegion,VkStridedDeviceAddressRegionKHR & missShaderBindingTableRegion,VkStridedDeviceAddressRegionKHR & callableShaderBindingTableRegion)418 void CheckerboardConfiguration::initShaderBindingTables (de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
419 Context& context,
420 TestParams& testParams,
421 VkPipeline pipeline,
422 deUint32 shaderGroupHandleSize,
423 deUint32 shaderGroupBaseAlignment,
424 de::MovePtr<BufferWithMemory>& raygenShaderBindingTable,
425 de::MovePtr<BufferWithMemory>& hitShaderBindingTable,
426 de::MovePtr<BufferWithMemory>& missShaderBindingTable,
427 de::MovePtr<BufferWithMemory>& callableShaderBindingTable,
428 VkStridedDeviceAddressRegionKHR& raygenShaderBindingTableRegion,
429 VkStridedDeviceAddressRegionKHR& hitShaderBindingTableRegion,
430 VkStridedDeviceAddressRegionKHR& missShaderBindingTableRegion,
431 VkStridedDeviceAddressRegionKHR& callableShaderBindingTableRegion)
432 {
433 const DeviceInterface& vkd = context.getDeviceInterface();
434 const VkDevice device = context.getDevice();
435 Allocator& allocator = context.getDefaultAllocator();
436
437 std::vector<deUint32> shaderCount = getShaderCounts();
438
439 // shaderBindingTableOffset must be multiple of shaderGroupBaseAlignment
440 deUint32 shaderBindingTableOffset = testParams.sbtOffset * shaderGroupBaseAlignment;
441
442 // ShaderRecordKHR size must be multiple of shaderGroupHandleSize
443 deUint32 shaderRecordAlignedSize = deAlign32(shaderGroupHandleSize + deUint32(sizeof(tcu::UVec4)), shaderGroupHandleSize);
444 switch (testParams.shaderTestType)
445 {
446 case STT_HIT:
447 {
448 raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
449 if(testParams.shaderRecordPresent)
450 hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, shaderCount[STT_HIT], 0u, 0u, MemoryRequirement::Any, 0u, shaderBindingTableOffset, sizeof(tcu::UVec4));
451 else
452 hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, shaderCount[STT_HIT], 0u, 0u, MemoryRequirement::Any, 0u, shaderBindingTableOffset);
453 missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1 + shaderCount[STT_HIT], 1 );
454
455 raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
456 if (testParams.shaderRecordPresent)
457 hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), shaderBindingTableOffset), shaderRecordAlignedSize, shaderCount[STT_HIT] * shaderRecordAlignedSize);
458 else
459 hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), shaderBindingTableOffset), shaderGroupHandleSize, shaderCount[STT_HIT] * shaderGroupHandleSize);
460 missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
461 callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
462
463 // fill ShaderRecordKHR data
464 if (testParams.shaderRecordPresent)
465 {
466 deUint8* hitAddressBegin = (deUint8*)hitShaderBindingTable->getAllocation().getHostPtr() + shaderBindingTableOffset;
467
468 for (size_t idx = 0; idx < shaderCount[STT_HIT]; ++idx)
469 {
470 deUint8* shaderRecordAddress = hitAddressBegin + idx * shaderRecordAlignedSize + size_t(shaderGroupHandleSize);
471 tcu::UVec4 shaderRecord(deUint32(idx), 0, 0, 0);
472 deMemcpy(shaderRecordAddress, &shaderRecord, sizeof(tcu::UVec4));
473 }
474
475 flushMappedMemoryRange(vkd, device, hitShaderBindingTable->getAllocation().getMemory(), hitShaderBindingTable->getAllocation().getOffset(), VK_WHOLE_SIZE);
476 }
477 break;
478 }
479 case STT_MISS:
480 {
481 raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
482 hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1 );
483 if (testParams.shaderRecordPresent)
484 missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, shaderCount[STT_MISS], 0u, 0u, MemoryRequirement::Any, 0u, shaderBindingTableOffset, sizeof(tcu::UVec4));
485 else
486 missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, shaderCount[STT_MISS], 0u, 0u, MemoryRequirement::Any, 0u, shaderBindingTableOffset);
487
488 raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
489 hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), 0, shaderGroupHandleSize);
490 if (testParams.shaderRecordPresent)
491 missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), shaderBindingTableOffset), shaderRecordAlignedSize, shaderCount[STT_MISS] * shaderRecordAlignedSize);
492 else
493 missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), shaderBindingTableOffset), shaderGroupHandleSize, shaderCount[STT_MISS] * shaderGroupHandleSize);
494 callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
495
496 if (testParams.shaderRecordPresent)
497 {
498 deUint8* missAddressBegin = (deUint8*)missShaderBindingTable->getAllocation().getHostPtr() + shaderBindingTableOffset;
499
500 for (size_t idx = 0; idx < shaderCount[STT_MISS]; ++idx)
501 {
502 deUint8* shaderRecordAddress = missAddressBegin + idx * shaderRecordAlignedSize + size_t(shaderGroupHandleSize);
503 tcu::UVec4 shaderRecord(deUint32(idx), 0, 0, 0);
504 deMemcpy(shaderRecordAddress, &shaderRecord, sizeof(tcu::UVec4));
505 }
506
507 flushMappedMemoryRange(vkd, device, missShaderBindingTable->getAllocation().getMemory(), missShaderBindingTable->getAllocation().getOffset(), VK_WHOLE_SIZE);
508 }
509 break;
510 }
511 case STT_CALL:
512 {
513 raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
514 hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, shaderCount[STT_CALL]);
515 missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1 + shaderCount[STT_CALL], 1 );
516 if (testParams.shaderRecordPresent)
517 callableShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2 + shaderCount[STT_CALL], shaderCount[STT_CALL], 0u, 0u, MemoryRequirement::Any, 0u, shaderBindingTableOffset, sizeof(tcu::UVec4));
518 else
519 callableShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2 + shaderCount[STT_CALL], shaderCount[STT_CALL], 0u, 0u, MemoryRequirement::Any, 0u, shaderBindingTableOffset);
520
521 raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
522 hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderCount[STT_CALL] * shaderGroupHandleSize);
523 missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
524 if (testParams.shaderRecordPresent)
525 callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, callableShaderBindingTable->get(), shaderBindingTableOffset), shaderRecordAlignedSize, shaderCount[STT_CALL] * shaderRecordAlignedSize);
526 else
527 callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, callableShaderBindingTable->get(), shaderBindingTableOffset), shaderGroupHandleSize, shaderCount[STT_CALL] * shaderGroupHandleSize);
528
529 if (testParams.shaderRecordPresent)
530 {
531 deUint8* callAddressBegin = (deUint8*)callableShaderBindingTable->getAllocation().getHostPtr() + shaderBindingTableOffset;
532
533 for (size_t idx = 0; idx < shaderCount[STT_CALL]; ++idx)
534 {
535 deUint8* shaderRecordAddress = callAddressBegin + idx * shaderRecordAlignedSize + size_t(shaderGroupHandleSize);
536 tcu::UVec4 shaderRecord(deUint32(idx), 0, 0, 0);
537 deMemcpy(shaderRecordAddress, &shaderRecord, sizeof(tcu::UVec4));
538 }
539 flushMappedMemoryRange(vkd, device, callableShaderBindingTable->getAllocation().getMemory(), callableShaderBindingTable->getAllocation().getOffset(), VK_WHOLE_SIZE);
540 }
541 break;
542 }
543 default:
544 TCU_THROW(InternalError, "Wrong shader test type");
545 }
546 }
547
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)548 bool CheckerboardConfiguration::verifyImage (BufferWithMemory* resultBuffer, Context& context, TestParams& testParams)
549 {
550 // create result image
551 tcu::TextureFormat imageFormat = vk::mapVkFormat(getResultImageFormat());
552 tcu::ConstPixelBufferAccess resultAccess(imageFormat, testParams.width, testParams.height, 1, resultBuffer->getAllocation().getHostPtr());
553
554 // recreate geometry indices and instance offsets
555 std::vector<tcu::UVec4> corners;
556 for (deUint32 y = 0; y < testParams.height; ++y)
557 for (deUint32 x = 0; x < testParams.width; ++x)
558 {
559 if (((x + y) % 2) == 0)
560 continue;
561 corners.push_back(tcu::UVec4(x, y, 0, 0));
562 }
563 de::Random rnd(SBT_RANDOM_SEED);
564 rnd.shuffle(begin(corners), end(corners));
565
566 deUint32 instanceOffset = 0;
567 for (size_t cornerNdx = 0; cornerNdx < corners.size(); cornerNdx += HIT_GEOMETRY_COUNT, ++instanceOffset)
568 {
569 size_t geometryCount = std::min(corners.size() - cornerNdx, size_t(HIT_GEOMETRY_COUNT));
570 deUint32 geometryIndex = 0;
571 for (size_t idx = cornerNdx; idx < cornerNdx + geometryCount; ++idx, ++geometryIndex)
572 {
573 corners[idx].z() = instanceOffset;
574 corners[idx].w() = geometryIndex;
575 }
576 }
577
578 std::vector<deUint32> reference(testParams.width * testParams.height);
579 tcu::PixelBufferAccess referenceAccess(imageFormat, testParams.width, testParams.height, 1, reference.data());
580 // clear image with miss values
581 tcu::UVec4 missValue((testParams.shaderTestType == STT_MISS) ? testParams.sbtRecordOffset : 0, 0, 0, 0);
582 tcu::clear(referenceAccess, missValue);
583
584 // for each pixel - set its color to proper value
585 for (const auto& pixel : corners)
586 {
587 deUint32 shaderIndex;
588 switch (testParams.shaderTestType)
589 {
590 case STT_HIT:
591 {
592 shaderIndex = testParams.sbtRecordOffset + pixel.z() + pixel.w() * testParams.sbtRecordStride;
593 break;
594 }
595 case STT_MISS:
596 {
597 shaderIndex = 0;// pixel.z();
598 break;
599 }
600 case STT_CALL:
601 {
602 shaderIndex = testParams.sbtRecordOffset + pixel.z() + pixel.w() * testParams.sbtRecordStride;
603 break;
604 }
605 default:
606 TCU_THROW(InternalError, "Wrong shader test type");
607 }
608
609 referenceAccess.setPixel(tcu::UVec4(shaderIndex, 0, 0, 0), pixel.x(), pixel.y());
610 }
611
612 // compare result and reference
613 return tcu::intThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess, resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
614 }
615
getResultImageFormat()616 VkFormat CheckerboardConfiguration::getResultImageFormat ()
617 {
618 return VK_FORMAT_R32_UINT;
619 }
620
getResultImageFormatSize()621 size_t CheckerboardConfiguration::getResultImageFormatSize ()
622 {
623 return sizeof(deUint32);
624 }
625
getClearValue()626 VkClearValue CheckerboardConfiguration::getClearValue ()
627 {
628 return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
629 }
630
631 class ShaderBindingTableIndexingTestCase : public TestCase
632 {
633 public:
634 ShaderBindingTableIndexingTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams data);
635 ~ShaderBindingTableIndexingTestCase (void);
636
637 virtual void checkSupport (Context& context) const;
638 virtual void initPrograms (SourceCollections& programCollection) const;
639 virtual TestInstance* createInstance (Context& context) const;
640 private:
641 TestParams m_data;
642 };
643
644 class ShaderBindingTableIndexingTestInstance : public TestInstance
645 {
646 public:
647 ShaderBindingTableIndexingTestInstance (Context& context, const TestParams& data);
648 ~ShaderBindingTableIndexingTestInstance (void);
649 tcu::TestStatus iterate (void);
650
651 protected:
652 de::MovePtr<BufferWithMemory> runTest ();
653 private:
654 TestParams m_data;
655 };
656
ShaderBindingTableIndexingTestCase(tcu::TestContext & context,const char * name,const char * desc,const TestParams data)657 ShaderBindingTableIndexingTestCase::ShaderBindingTableIndexingTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams data)
658 : vkt::TestCase (context, name, desc)
659 , m_data (data)
660 {
661 }
662
~ShaderBindingTableIndexingTestCase(void)663 ShaderBindingTableIndexingTestCase::~ShaderBindingTableIndexingTestCase (void)
664 {
665 }
666
checkSupport(Context & context) const667 void ShaderBindingTableIndexingTestCase::checkSupport (Context& context) const
668 {
669 context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
670 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
671
672 const VkPhysicalDeviceRayTracingPipelineFeaturesKHR& rayTracingPipelineFeaturesKHR = context.getRayTracingPipelineFeatures();
673 if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE )
674 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
675
676 const VkPhysicalDeviceAccelerationStructureFeaturesKHR& accelerationStructureFeaturesKHR = context.getAccelerationStructureFeatures();
677 if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
678 TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
679 }
680
initPrograms(SourceCollections & programCollection) const681 void ShaderBindingTableIndexingTestCase::initPrograms (SourceCollections& programCollection) const
682 {
683 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
684
685 std::vector<deUint32> shaderCount = getShaderCounts();
686
687 {
688 std::stringstream css;
689 css <<
690 "#version 460 core\n"
691 "#extension GL_EXT_ray_tracing : require\n"
692 "layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
693 "layout(r32ui, set = 0, binding = 0) uniform uimage2D result;\n"
694 "layout(set = 0, binding = 1) uniform TraceRaysParamsUBO\n"
695 "{\n"
696 " uvec4 trParams; // x = sbtRecordOffset, y = sbtRecordStride, z = missIndex\n"
697 "};\n"
698 "layout(set = 0, binding = 2) uniform accelerationStructureEXT topLevelAS;\n"
699 "\n"
700 "void main()\n"
701 "{\n"
702 " float tmin = 0.0;\n"
703 " float tmax = 1.0;\n"
704 " vec3 origin = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, 0.5f);\n"
705 " vec3 direct = vec3(0.0, 0.0, -1.0);\n"
706 " hitValue = uvec4(0,0,0,0);\n"
707 " traceRayEXT(topLevelAS, 0, 0xFF, trParams.x, trParams.y, trParams.z, origin, tmin, direct, tmax, 0);\n"
708 " imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n"
709 "}\n";
710 programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
711 }
712
713 for(deUint32 idx = 0; idx < shaderCount[STT_HIT]; ++idx)
714 {
715 std::stringstream css;
716 css <<
717 "#version 460 core\n"
718 "#extension GL_EXT_ray_tracing : require\n"
719 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
720 "void main()\n"
721 "{\n"
722 " hitValue = uvec4("<< idx << ",0,0,1);\n"
723 "}\n";
724 std::stringstream csname;
725 csname << "chit_" << idx;
726
727 programCollection.glslSources.add(csname.str()) << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
728 }
729
730 {
731 std::stringstream css;
732 css <<
733 "#version 460 core\n"
734 "#extension GL_EXT_ray_tracing : require\n"
735 "layout(shaderRecordEXT) buffer block\n"
736 "{\n"
737 " uvec4 info;\n"
738 "};\n"
739 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
740 "void main()\n"
741 "{\n"
742 " hitValue = info;\n"
743 "}\n";
744 programCollection.glslSources.add("chit_shaderRecord") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
745 }
746
747 for (deUint32 idx = 0; idx < shaderCount[STT_CALL]; ++idx)
748 {
749 std::stringstream css;
750 css <<
751 "#version 460 core\n"
752 "#extension GL_EXT_ray_tracing : require\n"
753 "layout(location = 0) callableDataEXT uvec4 value;\n"
754 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
755 "void main()\n"
756 "{\n"
757 " executeCallableEXT(" << idx << ", 0);\n"
758 " hitValue = value;\n"
759 "}\n";
760 std::stringstream csname;
761 csname << "chit_call_" << idx;
762
763 programCollection.glslSources.add(csname.str()) << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
764 }
765
766 for (deUint32 idx = 0; idx < shaderCount[STT_MISS]; ++idx)
767 {
768 std::stringstream css;
769 css <<
770 "#version 460 core\n"
771 "#extension GL_EXT_ray_tracing : require\n"
772 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
773 "void main()\n"
774 "{\n"
775 " hitValue = uvec4(" << idx <<",0,0,1);\n"
776 "}\n";
777 std::stringstream csname;
778 csname << "miss_" << idx;
779
780 programCollection.glslSources.add(csname.str()) << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
781 }
782
783 {
784 std::stringstream css;
785 css <<
786 "#version 460 core\n"
787 "#extension GL_EXT_ray_tracing : require\n"
788 "layout(shaderRecordEXT) buffer block\n"
789 "{\n"
790 " uvec4 info;\n"
791 "};\n"
792 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
793 "void main()\n"
794 "{\n"
795 " hitValue = info;\n"
796 "}\n";
797
798 programCollection.glslSources.add("miss_shaderRecord") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
799 }
800
801 for (deUint32 idx = 0; idx < shaderCount[STT_CALL]; ++idx)
802 {
803 std::stringstream css;
804 css <<
805 "#version 460 core\n"
806 "#extension GL_EXT_ray_tracing : require\n"
807 "layout(location = 0) callableDataInEXT uvec4 result;\n"
808 "void main()\n"
809 "{\n"
810 " result = uvec4(" << idx << ",0,0,1);\n"
811 "}\n";
812 std::stringstream csname;
813 csname << "call_" << idx;
814
815 programCollection.glslSources.add(csname.str()) << glu::CallableSource(updateRayTracingGLSL(css.str())) << buildOptions;
816 }
817
818 {
819 std::stringstream css;
820 css <<
821 "#version 460 core\n"
822 "#extension GL_EXT_ray_tracing : require\n"
823 "layout(shaderRecordEXT) buffer block\n"
824 "{\n"
825 " uvec4 info;\n"
826 "};\n"
827 "layout(location = 0) callableDataInEXT uvec4 result;\n"
828 "void main()\n"
829 "{\n"
830 " result = info;\n"
831 "}\n";
832
833 programCollection.glslSources.add("call_shaderRecord") << glu::CallableSource(updateRayTracingGLSL(css.str())) << buildOptions;
834 }
835 }
836
createInstance(Context & context) const837 TestInstance* ShaderBindingTableIndexingTestCase::createInstance (Context& context) const
838 {
839 return new ShaderBindingTableIndexingTestInstance(context, m_data);
840 }
841
ShaderBindingTableIndexingTestInstance(Context & context,const TestParams & data)842 ShaderBindingTableIndexingTestInstance::ShaderBindingTableIndexingTestInstance (Context& context, const TestParams& data)
843 : vkt::TestInstance (context)
844 , m_data (data)
845 {
846 }
847
~ShaderBindingTableIndexingTestInstance(void)848 ShaderBindingTableIndexingTestInstance::~ShaderBindingTableIndexingTestInstance (void)
849 {
850 }
851
runTest()852 de::MovePtr<BufferWithMemory> ShaderBindingTableIndexingTestInstance::runTest ()
853 {
854 const InstanceInterface& vki = m_context.getInstanceInterface();
855 const DeviceInterface& vkd = m_context.getDeviceInterface();
856 const VkDevice device = m_context.getDevice();
857 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
858 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
859 const VkQueue queue = m_context.getUniversalQueue();
860 Allocator& allocator = m_context.getDefaultAllocator();
861 const deUint32 pixelCount = m_data.width * m_data.height * 1;
862
863 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
864 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
865 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, ALL_RAY_TRACING_STAGES)
866 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
867 .build(vkd, device);
868 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
869 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
870 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
871 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
872 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
873 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
874 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
875
876 de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
877 m_data.testConfiguration->initRayTracingShaders(rayTracingPipeline, m_context, m_data);
878 Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
879
880 de::MovePtr<BufferWithMemory> raygenShaderBindingTable;
881 de::MovePtr<BufferWithMemory> hitShaderBindingTable;
882 de::MovePtr<BufferWithMemory> missShaderBindingTable;
883 de::MovePtr<BufferWithMemory> callableShaderBindingTable;
884 VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion;
885 VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion;
886 VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion;
887 VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion;
888 m_data.testConfiguration->initShaderBindingTables(rayTracingPipeline, m_context, m_data, *pipeline, getShaderGroupHandleSize(vki, physicalDevice), getShaderGroupBaseAlignment(vki, physicalDevice), raygenShaderBindingTable, hitShaderBindingTable, missShaderBindingTable, callableShaderBindingTable, raygenShaderBindingTableRegion, hitShaderBindingTableRegion, missShaderBindingTableRegion, callableShaderBindingTableRegion);
889
890 const VkFormat imageFormat = m_data.testConfiguration->getResultImageFormat();
891 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_data.width, m_data.height, imageFormat);
892 const VkImageSubresourceRange imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
893 const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
894 const Move<VkImageView> imageView = makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, imageFormat, imageSubresourceRange);
895
896 const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(pixelCount*m_data.testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
897 const VkImageSubresourceLayers resultBufferImageSubresourceLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
898 const VkBufferImageCopy resultBufferImageRegion = makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 1), resultBufferImageSubresourceLayers);
899 de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
900
901 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
902
903 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
904 const Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
905
906 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > bottomLevelAccelerationStructures;
907 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
908 de::MovePtr<BufferWithMemory> uniformBuffer;
909
910 beginCommandBuffer(vkd, *cmdBuffer, 0u);
911 {
912 const VkImageMemoryBarrier preImageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
913 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
914 **image, imageSubresourceRange);
915 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
916
917 const VkClearValue clearValue = m_data.testConfiguration->getClearValue();
918 vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
919
920 const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
921 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
922 **image, imageSubresourceRange);
923 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
924
925 bottomLevelAccelerationStructures = m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
926 for (auto& blas : bottomLevelAccelerationStructures)
927 blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
928 topLevelAccelerationStructure = m_data.testConfiguration->initTopAccelerationStructure(m_context, m_data, bottomLevelAccelerationStructures);
929 topLevelAccelerationStructure->createAndBuild(vkd, device, *cmdBuffer, allocator);
930
931 uniformBuffer = m_data.testConfiguration->initUniformBuffer(m_context, m_data);
932 VkDescriptorBufferInfo uniformBufferInfo = makeDescriptorBufferInfo(uniformBuffer->get(), 0ull, sizeof(tcu::UVec4));
933
934 const TopLevelAccelerationStructure* topLevelAccelerationStructurePtr = topLevelAccelerationStructure.get();
935 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet =
936 {
937 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
938 DE_NULL, // const void* pNext;
939 1u, // deUint32 accelerationStructureCount;
940 topLevelAccelerationStructurePtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
941 };
942
943 DescriptorSetUpdateBuilder()
944 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
945 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferInfo)
946 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
947 .update(vkd, device);
948
949 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
950
951 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
952
953 cmdTraceRays(vkd,
954 *cmdBuffer,
955 &raygenShaderBindingTableRegion,
956 &missShaderBindingTableRegion,
957 &hitShaderBindingTableRegion,
958 &callableShaderBindingTableRegion,
959 m_data.width, m_data.height, 1);
960
961 const VkMemoryBarrier postTraceMemoryBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
962 const VkMemoryBarrier postCopyMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
963 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
964
965 vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, &resultBufferImageRegion);
966
967 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
968 }
969 endCommandBuffer(vkd, *cmdBuffer);
970
971 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
972
973 invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
974
975 return resultBuffer;
976 }
977
iterate(void)978 tcu::TestStatus ShaderBindingTableIndexingTestInstance::iterate (void)
979 {
980 // run test using arrays of pointers
981 const de::MovePtr<BufferWithMemory> buffer = runTest();
982
983 if (!m_data.testConfiguration->verifyImage(buffer.get(), m_context, m_data))
984 return tcu::TestStatus::fail("Fail");
985 return tcu::TestStatus::pass("Pass");
986 }
987
988 /*
989
990 Test the advertised shader group handle alignment requirements work as expected. The tests will prepare shader binding tables using
991 shader record buffers for padding and achieving the desired alignments.
992
993 +-------------------------------------------
994 | Shader | Shader | Aligned |
995 | Group | Record | Shader | ...
996 | Handle | Buffer | Group |
997 | | (padding) | Handle |
998 +-------------------------------------------
999
1000 The number of geometries to try (hence the number of alignments and shader record buffers to try) is 32/align + 1, so 33 in the case
1001 of align=1, and 2 in the case of align=32. This allows us to test all possible alignment values.
1002
1003 Geometries are triangles put alongside the X axis. The base triangle is:
1004
1005 0,1| x
1006 | x x
1007 | x 0.5,0.5
1008 | x x x
1009 | x x
1010 | xxxxxxxxxxx
1011 +-------------
1012 0,0 1,0
1013
1014 A triangle surrounding point (0.5, 0.5), in the [0, 1] range of both the X and Y axis.
1015
1016 As more than one triangle is needed, each triangle is translated one more unit in the X axis, so each triangle is in the [i, i+1]
1017 range. The Y axis doesn't change, triangles are always in the [0,1] range.
1018
1019 Triangles have Z=5, and one ray is traced per triangle, origin (i+0.5, 0.5, 0) direction (0, 0, 1), where i is gl_LaunchIDEXT.x.
1020
1021 For each geometry, the shader record buffer contents vary depending on the geometry index and the desired alignment (padding).
1022
1023 Alignment Element Type Element Count Data
1024 1 uint8_t 1 0x80 | geometryID
1025 2 uint16_t 1 0xABC0 | geometryID
1026 4+ uint32_t alignment/4 For each element: 0xABCDE0F0 | (element << 8) | geometryID
1027
1028 The test will try to verify everything works properly and all shader record buffers can be read with the right values.
1029
1030 */
1031 struct ShaderGroupHandleAlignmentParams
1032 {
1033 const uint32_t alignment;
1034
ShaderGroupHandleAlignmentParamsvkt::RayTracing::__anonfbabc3b70111::ShaderGroupHandleAlignmentParams1035 ShaderGroupHandleAlignmentParams (uint32_t alignment_)
1036 : alignment (alignment_)
1037 {
1038 DE_ASSERT(alignment >= 1u && alignment <= 32u);
1039 DE_ASSERT(deIsPowerOfTwo32(static_cast<int>(alignment)));
1040 }
1041
geometryCountvkt::RayTracing::__anonfbabc3b70111::ShaderGroupHandleAlignmentParams1042 uint32_t geometryCount () const
1043 {
1044 return (32u / alignment + 1u);
1045 }
1046
shaderRecordElementCountvkt::RayTracing::__anonfbabc3b70111::ShaderGroupHandleAlignmentParams1047 uint32_t shaderRecordElementCount () const
1048 {
1049 return ((alignment <= 4u) ? 1u : (alignment / 4u));
1050 }
1051
glslElementTypevkt::RayTracing::__anonfbabc3b70111::ShaderGroupHandleAlignmentParams1052 std::string glslElementType () const
1053 {
1054 if (alignment == 1u)
1055 return "uint8_t";
1056 if (alignment == 2u)
1057 return "uint16_t";
1058 return "uint32_t";
1059 }
1060
glslExtensionvkt::RayTracing::__anonfbabc3b70111::ShaderGroupHandleAlignmentParams1061 std::string glslExtension () const
1062 {
1063 if (alignment == 1u)
1064 return "GL_EXT_shader_explicit_arithmetic_types_int8";
1065 if (alignment == 2u)
1066 return "GL_EXT_shader_explicit_arithmetic_types_int16";
1067 return "GL_EXT_shader_explicit_arithmetic_types_int32";
1068 }
1069
getRecordDatavkt::RayTracing::__anonfbabc3b70111::ShaderGroupHandleAlignmentParams1070 std::vector<uint8_t> getRecordData (uint32_t geometryID) const
1071 {
1072 std::vector<uint8_t> recordData;
1073 switch (alignment)
1074 {
1075 case 1u:
1076 recordData.push_back(static_cast<uint8_t>(0x80u | geometryID));
1077 break;
1078 case 2u:
1079 recordData.push_back(uint8_t{0xABu});
1080 recordData.push_back(static_cast<uint8_t>(0xC0u | geometryID));
1081 break;
1082 default:
1083 {
1084 const auto elemCount = shaderRecordElementCount();
1085 for (uint32_t i = 0u; i < elemCount; ++i)
1086 {
1087 recordData.push_back(uint8_t{0xABu});
1088 recordData.push_back(uint8_t{0xCDu});
1089 recordData.push_back(static_cast<uint8_t>(0xE0u | i));
1090 recordData.push_back(static_cast<uint8_t>(0xF0u | geometryID));
1091 }
1092 }
1093 break;
1094 }
1095 return recordData;
1096 }
1097 };
1098
1099 class ShaderGroupHandleAlignmentCase : public TestCase
1100 {
1101 public:
ShaderGroupHandleAlignmentCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const ShaderGroupHandleAlignmentParams & params)1102 ShaderGroupHandleAlignmentCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const ShaderGroupHandleAlignmentParams& params)
1103 : TestCase (testCtx, name, description)
1104 , m_params (params)
1105 {
1106 }
~ShaderGroupHandleAlignmentCase(void)1107 virtual ~ShaderGroupHandleAlignmentCase (void) {}
1108
1109 void checkSupport (Context& context) const override;
1110 void initPrograms (vk::SourceCollections& programCollection) const override;
1111 TestInstance* createInstance (Context& context) const override;
1112
1113 protected:
1114 ShaderGroupHandleAlignmentParams m_params;
1115 };
1116
1117 class ShaderGroupHandleAlignmentInstance : public TestInstance
1118 {
1119 public:
ShaderGroupHandleAlignmentInstance(Context & context,const ShaderGroupHandleAlignmentParams & params)1120 ShaderGroupHandleAlignmentInstance (Context& context, const ShaderGroupHandleAlignmentParams& params)
1121 : TestInstance (context)
1122 , m_params (params)
1123 {}
~ShaderGroupHandleAlignmentInstance(void)1124 virtual ~ShaderGroupHandleAlignmentInstance (void) {}
1125
1126 tcu::TestStatus iterate (void) override;
1127
1128 protected:
1129 ShaderGroupHandleAlignmentParams m_params;
1130 };
1131
checkSupport(Context & context) const1132 void ShaderGroupHandleAlignmentCase::checkSupport (Context& context) const
1133 {
1134 context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
1135 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
1136
1137 const auto& vki = context.getInstanceInterface();
1138 const auto physicalDevice = context.getPhysicalDevice();
1139 const auto rtProperties = makeRayTracingProperties(vki, physicalDevice);
1140
1141 if (m_params.alignment < rtProperties->getShaderGroupHandleAlignment())
1142 TCU_THROW(NotSupportedError, "Required shader group handle alignment not supported");
1143
1144 switch (m_params.alignment)
1145 {
1146 case 1u:
1147 {
1148 const auto& int8Features = context.getShaderFloat16Int8Features();
1149 if (!int8Features.shaderInt8)
1150 TCU_THROW(NotSupportedError, "shaderInt8 not supported");
1151
1152 const auto& int8StorageFeatures = context.get8BitStorageFeatures();
1153 if (!int8StorageFeatures.storageBuffer8BitAccess)
1154 TCU_THROW(NotSupportedError, "storageBuffer8BitAccess not supported");
1155 }
1156 break;
1157
1158 case 2u:
1159 {
1160 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_INT16);
1161
1162 const auto& int16StorageFeatures = context.get16BitStorageFeatures();
1163 if (!int16StorageFeatures.storageBuffer16BitAccess)
1164 TCU_THROW(NotSupportedError, "storageBuffer16BitAccess not supported");
1165 }
1166 break;
1167
1168 default:
1169 break;
1170 }
1171 }
1172
initPrograms(vk::SourceCollections & programCollection) const1173 void ShaderGroupHandleAlignmentCase::initPrograms (vk::SourceCollections& programCollection) const
1174 {
1175 const ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1176
1177 const auto elemType = m_params.glslElementType();
1178 const auto geometryCount = m_params.geometryCount();
1179 const auto elementCount = m_params.shaderRecordElementCount();
1180 const auto extension = m_params.glslExtension();
1181
1182 std::ostringstream descriptors;
1183 descriptors
1184 << "layout(set=0, binding=0) uniform accelerationStructureEXT topLevelAS;\n"
1185 << "layout(set=0, binding=1, std430) buffer SSBOBlock {\n"
1186 << " " << elemType << " data[" << geometryCount << "][" << elementCount << "];\n"
1187 << "} ssbo;\n"
1188 ;
1189 const auto descriptorsStr = descriptors.str();
1190
1191 std::ostringstream commonHeader;
1192 commonHeader
1193 << "#version 460 core\n"
1194 << "#extension GL_EXT_ray_tracing : require\n"
1195 << "#extension " << extension << " : require\n"
1196 ;
1197 const auto commontHeaderStr = commonHeader.str();
1198
1199 std::ostringstream rgen;
1200 rgen
1201 << commontHeaderStr
1202 << "\n"
1203 << descriptorsStr
1204 << "layout(location=0) rayPayloadEXT vec4 unused;\n"
1205 << "\n"
1206 << "void main()\n"
1207 << "{\n"
1208 << " const uint rayFlags = 0;\n"
1209 << " const uint cullMask = 0xFF;\n"
1210 << " const float tMin = 0.0;\n"
1211 << " const float tMax = 10.0;\n"
1212 << " const vec3 origin = vec3(float(gl_LaunchIDEXT.x) + 0.5, 0.5, 0.0);\n"
1213 << " const vec3 direction = vec3(0.0, 0.0, 1.0);\n"
1214 << " const uint sbtOffset = 0;\n"
1215 << " const uint sbtStride = 1;\n"
1216 << " const uint missIndex = 0;\n"
1217 << " traceRayEXT(topLevelAS, rayFlags, cullMask, sbtOffset, sbtStride, missIndex, origin, tMin, direction, tMax, 0);\n"
1218 << "}\n"
1219 ;
1220
1221 std::ostringstream chit;
1222 chit
1223 << commontHeaderStr
1224 << "\n"
1225 << descriptorsStr
1226 << "layout(location=0) rayPayloadInEXT vec4 unused;\n"
1227 << "layout(shaderRecordEXT, std430) buffer srbBlock {\n"
1228 << " " << elemType << " data[" << elementCount << "];\n"
1229 << "} srb;\n"
1230 << "\n"
1231 << "void main()\n"
1232 << "{\n"
1233 << " for (uint i = 0; i < " << elementCount << "; ++i) {\n"
1234 << " ssbo.data[gl_LaunchIDEXT.x][i] = srb.data[i];\n"
1235 << " }\n"
1236 << "}\n"
1237 ;
1238
1239 std::ostringstream miss;
1240 miss
1241 << commontHeaderStr
1242 << "\n"
1243 << descriptorsStr
1244 << "layout(location=0) rayPayloadInEXT vec4 unused;\n"
1245 << "\n"
1246 << "void main()\n"
1247 << "{\n"
1248 << "}\n"
1249 ;
1250
1251 programCollection.glslSources.add("rgen") << glu::RaygenSource(rgen.str()) << buildOptions;
1252 programCollection.glslSources.add("chit") << glu::ClosestHitSource(chit.str()) << buildOptions;
1253 programCollection.glslSources.add("miss") << glu::MissSource(miss.str()) << buildOptions;
1254 }
1255
createInstance(Context & context) const1256 TestInstance* ShaderGroupHandleAlignmentCase::createInstance (Context& context) const
1257 {
1258 return new ShaderGroupHandleAlignmentInstance(context, m_params);
1259 }
1260
iterate(void)1261 tcu::TestStatus ShaderGroupHandleAlignmentInstance::iterate (void)
1262 {
1263 const auto& vki = m_context.getInstanceInterface();
1264 const auto physDev = m_context.getPhysicalDevice();
1265 const auto& vkd = m_context.getDeviceInterface();
1266 const auto device = m_context.getDevice();
1267 auto& alloc = m_context.getDefaultAllocator();
1268 const auto qIndex = m_context.getUniversalQueueFamilyIndex();
1269 const auto queue = m_context.getUniversalQueue();
1270 const auto stages = (VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR);
1271 const auto geoCount = m_params.geometryCount();
1272 const auto triangleZ = 5.0f;
1273
1274 // Command pool and buffer.
1275 const auto cmdPool = makeCommandPool(vkd, device, qIndex);
1276 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1277 const auto cmdBuffer = cmdBufferPtr.get();
1278
1279 beginCommandBuffer(vkd, cmdBuffer);
1280
1281 // Build acceleration structures.
1282 auto topLevelAS = makeTopLevelAccelerationStructure();
1283 auto bottomLevelAS = makeBottomLevelAccelerationStructure();
1284
1285 // Create the needed amount of geometries (triangles) with the right coordinates.
1286 const tcu::Vec3 baseLocation (0.5f, 0.5f, triangleZ);
1287 const float vertexOffset = 0.25f; // From base location, to build a triangle around it.
1288
1289 for (uint32_t i = 0; i < geoCount; ++i)
1290 {
1291 // Triangle "center" or base location.
1292 const tcu::Vec3 triangleLocation (baseLocation.x() + static_cast<float>(i), baseLocation.y(), baseLocation.z());
1293
1294 // Actual triangle.
1295 const std::vector<tcu::Vec3> triangle
1296 {
1297 tcu::Vec3(triangleLocation.x() - vertexOffset, triangleLocation.y() - vertexOffset, triangleLocation.z()),
1298 tcu::Vec3(triangleLocation.x() + vertexOffset, triangleLocation.y() - vertexOffset, triangleLocation.z()),
1299 tcu::Vec3(triangleLocation.x(), triangleLocation.y() + vertexOffset, triangleLocation.z()),
1300 };
1301
1302 bottomLevelAS->addGeometry(triangle, true/*triangles*/);
1303 }
1304
1305 bottomLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
1306
1307 de::SharedPtr<BottomLevelAccelerationStructure> blasSharedPtr (bottomLevelAS.release());
1308 topLevelAS->setInstanceCount(1);
1309 topLevelAS->addInstance(blasSharedPtr, identityMatrix3x4, 0u, 0xFF, 0u, VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR);
1310 topLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
1311
1312 // Get some ray tracing properties.
1313 uint32_t shaderGroupHandleSize = 0u;
1314 uint32_t shaderGroupBaseAlignment = 1u;
1315 {
1316 const auto rayTracingPropertiesKHR = makeRayTracingProperties(vki, physDev);
1317 shaderGroupHandleSize = rayTracingPropertiesKHR->getShaderGroupHandleSize();
1318 shaderGroupBaseAlignment = rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
1319 }
1320
1321 // SSBO to copy results over from the shaders.
1322 const auto shaderRecordSize = m_params.alignment;
1323 const auto hitSBTStride = shaderGroupHandleSize + shaderRecordSize;
1324 const auto ssboSize = static_cast<VkDeviceSize>(geoCount * hitSBTStride);
1325 const auto ssboInfo = makeBufferCreateInfo(ssboSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1326 BufferWithMemory ssbo (vkd, device, alloc, ssboInfo, MemoryRequirement::HostVisible);
1327 auto& ssboAlloc = ssbo.getAllocation();
1328 void* ssboData = ssboAlloc.getHostPtr();
1329
1330 deMemset(ssboData, 0, static_cast<size_t>(ssboSize));
1331
1332 // Descriptor set layout and pipeline layout.
1333 DescriptorSetLayoutBuilder setLayoutBuilder;
1334 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, stages);
1335 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stages);
1336 const auto setLayout = setLayoutBuilder.build(vkd, device);
1337 const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
1338
1339 // Descriptor pool and set.
1340 DescriptorPoolBuilder poolBuilder;
1341 poolBuilder.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
1342 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
1343 const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1344 const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
1345
1346 // Update descriptor set.
1347 {
1348 const VkWriteDescriptorSetAccelerationStructureKHR accelDescInfo =
1349 {
1350 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
1351 nullptr,
1352 1u,
1353 topLevelAS.get()->getPtr(),
1354 };
1355
1356 const auto ssboDescInfo = makeDescriptorBufferInfo(ssbo.get(), 0ull, ssboSize);
1357
1358 DescriptorSetUpdateBuilder updateBuilder;
1359 updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelDescInfo);
1360 updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboDescInfo);
1361 updateBuilder.update(vkd, device);
1362 }
1363
1364 // Shader modules.
1365 auto rgenModule = makeVkSharedPtr(createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0));
1366 auto missModule = makeVkSharedPtr(createShaderModule(vkd, device, m_context.getBinaryCollection().get("miss"), 0));
1367 auto chitModule = makeVkSharedPtr(createShaderModule(vkd, device, m_context.getBinaryCollection().get("chit"), 0));
1368
1369 // Create raytracing pipeline and shader binding tables.
1370 Move<VkPipeline> pipeline;
1371
1372 de::MovePtr<BufferWithMemory> raygenSBT;
1373 de::MovePtr<BufferWithMemory> missSBT;
1374 de::MovePtr<BufferWithMemory> hitSBT;
1375 de::MovePtr<BufferWithMemory> callableSBT;
1376
1377 VkStridedDeviceAddressRegionKHR raygenSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1378 VkStridedDeviceAddressRegionKHR missSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1379 VkStridedDeviceAddressRegionKHR hitSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1380 VkStridedDeviceAddressRegionKHR callableSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1381
1382 // Create shader record buffer data.
1383 using DataVec = std::vector<uint8_t>;
1384
1385 std::vector<DataVec> srbData;
1386 for (uint32_t i = 0; i < geoCount; ++i)
1387 {
1388 srbData.emplace_back(m_params.getRecordData(i));
1389 }
1390
1391 std::vector<const void*> srbDataPtrs;
1392 srbDataPtrs.reserve(srbData.size());
1393 std::transform(begin(srbData), end(srbData), std::back_inserter(srbDataPtrs), [](const DataVec& data) { return data.data(); });
1394
1395 // Generate ids for the closest hit and miss shaders according to the test parameters.
1396 {
1397 const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1398
1399 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenModule, 0u);
1400 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, missModule, 1u);
1401
1402 for (uint32_t i = 0; i < geoCount; ++i)
1403 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, chitModule, 2u + i);
1404
1405 pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout.get());
1406
1407 raygenSBT = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0u, 1u);
1408 raygenSBTRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1409
1410 missSBT = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 1u, 1u);
1411 missSBTRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1412
1413 hitSBT = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 2u, geoCount,
1414 0u, 0u, MemoryRequirement::Any, 0u, 0u, shaderRecordSize, srbDataPtrs.data(), false/*autoalign*/);
1415 hitSBTRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitSBT->get(), 0), hitSBTStride, hitSBTStride*geoCount);
1416 }
1417
1418 // Trace rays and verify ssbo contents.
1419 vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.get());
1420 vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
1421 vkd.cmdTraceRaysKHR(cmdBuffer, &raygenSBTRegion, &missSBTRegion, &hitSBTRegion, &callableSBTRegion, geoCount, 1u, 1u);
1422 const auto shaderToHostBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1423 cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_HOST_BIT, &shaderToHostBarrier);
1424
1425 endCommandBuffer(vkd, cmdBuffer);
1426 submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1427
1428 invalidateAlloc(vkd, device, ssboAlloc);
1429
1430 // Verify SSBO.
1431 const auto ssboDataAsBytes = reinterpret_cast<const uint8_t*>(ssboData);
1432 size_t ssboDataIdx = 0u;
1433 bool fail = false;
1434 auto& log = m_context.getTestContext().getLog();
1435
1436 for (const auto& dataVec : srbData)
1437 for (const uint8_t byte : dataVec)
1438 {
1439 const uint8_t outputByte = ssboDataAsBytes[ssboDataIdx++];
1440 if (byte != outputByte)
1441 {
1442 std::ostringstream msg;
1443 msg
1444 << std::hex << std::setfill('0')
1445 << "Unexpectd output data: "
1446 << "0x" << std::setw(2) << static_cast<int>(outputByte)
1447 << " vs "
1448 << "0x" << std::setw(2) << static_cast<int>(byte)
1449 ;
1450 log << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
1451 fail = true;
1452 }
1453 }
1454
1455 if (fail)
1456 return tcu::TestStatus::fail("Unexpected output data found; check log for details");
1457 return tcu::TestStatus::pass("Pass");
1458 }
1459
1460 } // anonymous
1461
createShaderBindingTableTests(tcu::TestContext & testCtx)1462 tcu::TestCaseGroup* createShaderBindingTableTests (tcu::TestContext& testCtx)
1463 {
1464 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_binding_table", "Tests veryfying shader binding tables"));
1465
1466 struct ShaderTestTypeData
1467 {
1468 ShaderTestType shaderTestType;
1469 const char* name;
1470 } shaderTestTypes[] =
1471 {
1472 { STT_HIT, "indexing_hit" },
1473 { STT_MISS, "indexing_miss" },
1474 { STT_CALL, "indexing_call" },
1475 };
1476
1477 struct ShaderBufferOffsetData
1478 {
1479 deUint32 sbtOffset;
1480 const char* name;
1481 } shaderBufferOffsets[] =
1482 {
1483 { 0u, "sbt_offset_0" },
1484 { 4u, "sbt_offset_4" },
1485 { 7u, "sbt_offset_7" },
1486 { 16u, "sbt_offset_16" },
1487 };
1488
1489 struct ShaderRecordData
1490 {
1491 bool present;
1492 const char* name;
1493 } shaderRecords[] =
1494 {
1495 { false, "no_shaderrecord" },
1496 { true, "shaderrecord" },
1497 };
1498
1499 for (size_t shaderTestNdx = 0; shaderTestNdx < DE_LENGTH_OF_ARRAY(shaderTestTypes); ++shaderTestNdx)
1500 {
1501 de::MovePtr<tcu::TestCaseGroup> shaderTestGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderTestTypes[shaderTestNdx].name, ""));
1502
1503 for (size_t sbtOffsetNdx = 0; sbtOffsetNdx < DE_LENGTH_OF_ARRAY(shaderBufferOffsets); ++sbtOffsetNdx)
1504 {
1505 de::MovePtr<tcu::TestCaseGroup> sbtOffsetGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderBufferOffsets[sbtOffsetNdx].name, ""));
1506
1507 for (size_t shaderRecordNdx = 0; shaderRecordNdx < DE_LENGTH_OF_ARRAY(shaderRecords); ++shaderRecordNdx)
1508 {
1509 de::MovePtr<tcu::TestCaseGroup> shaderRecordGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderRecords[shaderRecordNdx].name, ""));
1510
1511 deUint32 maxSbtRecordStride = (shaderTestTypes[shaderTestNdx].shaderTestType == STT_HIT) ? MAX_HIT_SBT_RECORD_STRIDE + 1 : 1;
1512 deUint32 maxSbtRecordOffset = MAX_SBT_RECORD_OFFSET;
1513 const deUint32 maxSbtRecordOffsetWithExtraBits = (shaderTestTypes[shaderTestNdx].shaderTestType == STT_MISS) ? MAX_SBT_RECORD_OFFSET | (~((1u << 16) - 1)) //< Only 16 least significant bits matter for miss indices
1514 : MAX_SBT_RECORD_OFFSET | (~((1u << 4) - 1)); //< Only 4 least significant bits matter for SBT record offsets
1515
1516 for (deUint32 sbtRecordOffset = 0; sbtRecordOffset <= maxSbtRecordOffset; ++sbtRecordOffset)
1517 for (deUint32 sbtRecordStride = 0; sbtRecordStride <= maxSbtRecordStride; ++sbtRecordStride)
1518 {
1519 if ((shaderTestTypes[shaderTestNdx].shaderTestType != STT_HIT) &&
1520 (sbtRecordStride == maxSbtRecordStride))
1521 {
1522 continue;
1523 }
1524
1525 TestParams testParams
1526 {
1527 CHECKERBOARD_WIDTH,
1528 CHECKERBOARD_HEIGHT,
1529 shaderTestTypes[shaderTestNdx].shaderTestType,
1530 shaderBufferOffsets[sbtOffsetNdx].sbtOffset,
1531 shaderRecords[shaderRecordNdx].present,
1532 sbtRecordOffset,
1533 (sbtRecordOffset == maxSbtRecordOffset) ? maxSbtRecordOffsetWithExtraBits
1534 : sbtRecordOffset,
1535 //< Only first 4 least significant bits matter for SBT record stride
1536 sbtRecordStride,
1537 (sbtRecordStride == maxSbtRecordStride) ? maxSbtRecordStride | (~((1u << 4) - 1))
1538 : sbtRecordStride,
1539 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration())
1540 };
1541
1542 std::stringstream str;
1543 str << sbtRecordOffset << "_" << sbtRecordStride;
1544
1545 if (testParams.sbtRecordStride != testParams.sbtRecordStridePassedToTraceRay)
1546 {
1547 str << "_extraSBTRecordStrideBits";
1548 }
1549
1550 if (testParams.sbtRecordOffset != testParams.sbtRecordOffsetPassedToTraceRay)
1551 {
1552 str << "_extrabits";
1553 }
1554
1555 shaderRecordGroup->addChild(new ShaderBindingTableIndexingTestCase(group->getTestContext(), str.str().c_str(), "", testParams));
1556 }
1557
1558 sbtOffsetGroup->addChild(shaderRecordGroup.release());
1559 }
1560
1561 shaderTestGroup->addChild(sbtOffsetGroup.release());
1562 }
1563
1564 group->addChild(shaderTestGroup.release());
1565 }
1566
1567 {
1568 const uint32_t kAlignments[] = { 1u, 2u, 4u, 8u, 16u, 32u };
1569 de::MovePtr<tcu::TestCaseGroup> handleAlignmentGroup (new tcu::TestCaseGroup(testCtx, "handle_alignment", "Test allowed handle alignments"));
1570
1571 for (const auto alignment : kAlignments)
1572 {
1573 const auto alignStr = std::to_string(alignment);
1574 const auto testName = "alignment_" + alignStr;
1575 const auto testDesc = "Check aligning shader group handles to " + alignStr + " bytes";
1576
1577 handleAlignmentGroup->addChild(new ShaderGroupHandleAlignmentCase(testCtx, testName, testDesc, ShaderGroupHandleAlignmentParams{alignment}));
1578 }
1579
1580 group->addChild(handleAlignmentGroup.release());
1581 }
1582
1583 return group.release();
1584 }
1585
1586 } // RayTracing
1587
1588 } // vkt
1589