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 } // anonymous
989
createShaderBindingTableTests(tcu::TestContext & testCtx)990 tcu::TestCaseGroup* createShaderBindingTableTests (tcu::TestContext& testCtx)
991 {
992 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_binding_table", "Tests veryfying shader binding tables"));
993
994 struct ShaderTestTypeData
995 {
996 ShaderTestType shaderTestType;
997 const char* name;
998 } shaderTestTypes[] =
999 {
1000 { STT_HIT, "indexing_hit" },
1001 { STT_MISS, "indexing_miss" },
1002 { STT_CALL, "indexing_call" },
1003 };
1004
1005 struct ShaderBufferOffsetData
1006 {
1007 deUint32 sbtOffset;
1008 const char* name;
1009 } shaderBufferOffsets[] =
1010 {
1011 { 0u, "sbt_offset_0" },
1012 { 4u, "sbt_offset_4" },
1013 { 7u, "sbt_offset_7" },
1014 { 16u, "sbt_offset_16" },
1015 };
1016
1017 struct ShaderRecordData
1018 {
1019 bool present;
1020 const char* name;
1021 } shaderRecords[] =
1022 {
1023 { false, "no_shaderrecord" },
1024 { true, "shaderrecord" },
1025 };
1026
1027 for (size_t shaderTestNdx = 0; shaderTestNdx < DE_LENGTH_OF_ARRAY(shaderTestTypes); ++shaderTestNdx)
1028 {
1029 de::MovePtr<tcu::TestCaseGroup> shaderTestGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderTestTypes[shaderTestNdx].name, ""));
1030
1031 for (size_t sbtOffsetNdx = 0; sbtOffsetNdx < DE_LENGTH_OF_ARRAY(shaderBufferOffsets); ++sbtOffsetNdx)
1032 {
1033 de::MovePtr<tcu::TestCaseGroup> sbtOffsetGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderBufferOffsets[sbtOffsetNdx].name, ""));
1034
1035 for (size_t shaderRecordNdx = 0; shaderRecordNdx < DE_LENGTH_OF_ARRAY(shaderRecords); ++shaderRecordNdx)
1036 {
1037 de::MovePtr<tcu::TestCaseGroup> shaderRecordGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderRecords[shaderRecordNdx].name, ""));
1038
1039 deUint32 maxSbtRecordStride = (shaderTestTypes[shaderTestNdx].shaderTestType == STT_HIT) ? MAX_HIT_SBT_RECORD_STRIDE + 1 : 1;
1040 deUint32 maxSbtRecordOffset = MAX_SBT_RECORD_OFFSET;
1041 const deUint32 maxSbtRecordOffsetWithExtraBits = (shaderTestTypes[shaderTestNdx].shaderTestType == STT_MISS) ? MAX_SBT_RECORD_OFFSET | (~((1u << 16) - 1)) //< Only 16 least significant bits matter for miss indices
1042 : MAX_SBT_RECORD_OFFSET | (~((1u << 4) - 1)); //< Only 4 least significant bits matter for SBT record offsets
1043
1044 for (deUint32 sbtRecordOffset = 0; sbtRecordOffset <= maxSbtRecordOffset; ++sbtRecordOffset)
1045 for (deUint32 sbtRecordStride = 0; sbtRecordStride <= maxSbtRecordStride; ++sbtRecordStride)
1046 {
1047 if ((shaderTestTypes[shaderTestNdx].shaderTestType != STT_HIT) &&
1048 (sbtRecordStride == maxSbtRecordStride))
1049 {
1050 continue;
1051 }
1052
1053 TestParams testParams
1054 {
1055 CHECKERBOARD_WIDTH,
1056 CHECKERBOARD_HEIGHT,
1057 shaderTestTypes[shaderTestNdx].shaderTestType,
1058 shaderBufferOffsets[sbtOffsetNdx].sbtOffset,
1059 shaderRecords[shaderRecordNdx].present,
1060 sbtRecordOffset,
1061 (sbtRecordOffset == maxSbtRecordOffset) ? maxSbtRecordOffsetWithExtraBits
1062 : sbtRecordOffset,
1063 //< Only first 4 least significant bits matter for SBT record stride
1064 sbtRecordStride,
1065 (sbtRecordStride == maxSbtRecordStride) ? maxSbtRecordStride | (~((1u << 4) - 1))
1066 : sbtRecordStride,
1067 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration())
1068 };
1069
1070 std::stringstream str;
1071 str << sbtRecordOffset << "_" << sbtRecordStride;
1072
1073 if (testParams.sbtRecordStride != testParams.sbtRecordStridePassedToTraceRay)
1074 {
1075 str << "_extraSBTRecordStrideBits";
1076 }
1077
1078 if (testParams.sbtRecordOffset != testParams.sbtRecordOffsetPassedToTraceRay)
1079 {
1080 str << "_extrabits";
1081 }
1082
1083 shaderRecordGroup->addChild(new ShaderBindingTableIndexingTestCase(group->getTestContext(), str.str().c_str(), "", testParams));
1084 }
1085
1086 sbtOffsetGroup->addChild(shaderRecordGroup.release());
1087 }
1088
1089 shaderTestGroup->addChild(sbtOffsetGroup.release());
1090 }
1091
1092 group->addChild(shaderTestGroup.release());
1093 }
1094
1095 return group.release();
1096 }
1097
1098 } // RayTracing
1099
1100 } // vkt
1101