• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  * Copyright (c) 2022 NVIDIA Corporation.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Ray Query Position Fetch Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktRayQueryPositionFetchTests.hpp"
26 #include "vktTestCase.hpp"
27 
28 #include "vkRayTracingUtil.hpp"
29 #include "vkObjUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkBufferWithMemory.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkBarrierUtil.hpp"
35 #include "vktTestGroupUtil.hpp"
36 
37 #include "deUniquePtr.hpp"
38 #include "deRandom.hpp"
39 
40 #include "tcuVectorUtil.hpp"
41 
42 #include <sstream>
43 #include <vector>
44 #include <iostream>
45 
46 namespace vkt
47 {
48 namespace RayQuery
49 {
50 
51 namespace
52 {
53 
54 using namespace vk;
55 
56 enum ShaderSourcePipeline
57 {
58 	SSP_GRAPHICS_PIPELINE,
59 	SSP_COMPUTE_PIPELINE,
60 	SSP_RAY_TRACING_PIPELINE
61 };
62 
63 enum ShaderSourceType
64 {
65 	SST_VERTEX_SHADER,
66 	SST_COMPUTE_SHADER,
67 	SST_RAY_GENERATION_SHADER,
68 };
69 
70 enum TestFlagBits
71 {
72 	TEST_FLAG_BIT_INSTANCE_TRANSFORM				= 1U << 0,
73 	TEST_FLAG_BIT_LAST								= 1U << 1,
74 };
75 
76 std::vector<std::string> testFlagBitNames =
77 {
78 	"instance_transform",
79 };
80 
81 struct TestParams
82 {
83 	ShaderSourceType		shaderSourceType;
84 	ShaderSourcePipeline	shaderSourcePipeline;
85 	vk::VkAccelerationStructureBuildTypeKHR	buildType;		// are we making AS on CPU or GPU
86 	VkFormat								vertexFormat;
87 	deUint32								testFlagMask;
88 };
89 
90 static constexpr deUint32 kNumThreadsAtOnce = 1024;
91 
92 
93 class PositionFetchCase : public TestCase
94 {
95 public:
96 							PositionFetchCase		(tcu::TestContext& testCtx, const std::string& name, const TestParams& params);
~PositionFetchCase(void)97 	virtual					~PositionFetchCase	(void) {}
98 
99 	virtual void			checkSupport				(Context& context) const;
100 	virtual void			initPrograms				(vk::SourceCollections& programCollection) const;
101 	virtual TestInstance*	createInstance				(Context& context) const;
102 
103 protected:
104 	TestParams				m_params;
105 };
106 
107 class PositionFetchInstance : public TestInstance
108 {
109 public:
110 								PositionFetchInstance		(Context& context, const TestParams& params);
~PositionFetchInstance(void)111 	virtual						~PositionFetchInstance	(void) {}
112 
113 	virtual tcu::TestStatus		iterate							(void);
114 
115 protected:
116 	TestParams					m_params;
117 };
118 
PositionFetchCase(tcu::TestContext & testCtx,const std::string & name,const TestParams & params)119 PositionFetchCase::PositionFetchCase (tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
120 	: TestCase	(testCtx, name)
121 	, m_params	(params)
122 {}
123 
checkSupport(Context & context) const124 void PositionFetchCase::checkSupport (Context& context) const
125 {
126 	context.requireDeviceFunctionality("VK_KHR_ray_query");
127 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
128 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_position_fetch");
129 
130 	const VkPhysicalDeviceRayQueryFeaturesKHR& rayQueryFeaturesKHR = context.getRayQueryFeatures();
131 	if (rayQueryFeaturesKHR.rayQuery == DE_FALSE)
132 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayQueryFeaturesKHR.rayQuery");
133 
134 	const VkPhysicalDeviceAccelerationStructureFeaturesKHR& accelerationStructureFeaturesKHR = context.getAccelerationStructureFeatures();
135 	if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
136 		TCU_THROW(TestError, "VK_KHR_ray_query requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
137 
138 	if (m_params.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR && accelerationStructureFeaturesKHR.accelerationStructureHostCommands == DE_FALSE)
139 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
140 
141 	const VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR& rayTracingPositionFetchFeaturesKHR = context.getRayTracingPositionFetchFeatures();
142 	if (rayTracingPositionFetchFeaturesKHR.rayTracingPositionFetch == DE_FALSE)
143 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDevicePositionFetchFeaturesKHR.rayTracingPositionFetch");
144 
145 	// Check supported vertex format.
146 	checkAccelerationStructureVertexBufferFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.vertexFormat);
147 
148 	if (m_params.shaderSourceType == SST_RAY_GENERATION_SHADER)
149 	{
150 		context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
151 
152 		const VkPhysicalDeviceRayTracingPipelineFeaturesKHR& rayTracingPipelineFeaturesKHR = context.getRayTracingPipelineFeatures();
153 
154 		if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE)
155 			TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
156 	}
157 
158 	switch (m_params.shaderSourceType)
159 	{
160 	case SST_VERTEX_SHADER:
161 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
162 		break;
163 	default:
164 		break;
165 	}
166 }
167 
initPrograms(vk::SourceCollections & programCollection) const168 void PositionFetchCase::initPrograms (vk::SourceCollections& programCollection) const
169 {
170 	const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
171 
172 	deUint32 numRays = 1; // XXX
173 
174 	std::ostringstream sharedHeader;
175 	sharedHeader
176 		<< "#version 460 core\n"
177 		<< "#extension GL_EXT_ray_query : require\n"
178 		<< "#extension GL_EXT_ray_tracing_position_fetch : require\n"
179 		<< "\n"
180 		<< "layout(set=0, binding=0) uniform accelerationStructureEXT topLevelAS;\n"
181 		<< "layout(set=0, binding=1, std430) buffer RayOrigins {\n"
182 		<< "  vec4 values[" << numRays << "];\n"
183 		<< "} origins;\n"
184 		<< "layout(set=0, binding=2, std430) buffer OutputPositions {\n"
185 		<< "  vec4 values[" << 3*numRays << "];\n"
186 		<< "} modes;\n";
187 
188 	std::ostringstream mainLoop;
189 	mainLoop
190 		<< "  while (index < " << numRays << ") {\n"
191 		//<< "     for (int i=0; i<3; i++) {\n"
192 		//<< "       modes.values[3*index.x+i] = vec4(i, 0.0, 5.0, 1.0);\n"
193 		//<< "     }\n"
194 		<< "    const uint  cullMask  = 0xFF;\n"
195 		<< "    const vec3  origin    = origins.values[index].xyz;\n"
196 		<< "    const vec3  direction = vec3(0.0, 0.0, -1.0);\n"
197 		<< "    const float tMin      = 0.0f;\n"
198 		<< "    const float tMax      = 2.0f;\n"
199 		<< "    rayQueryEXT rq;\n"
200 		<< "    rayQueryInitializeEXT(rq, topLevelAS, gl_RayFlagsNoneEXT, cullMask, origin, tMin, direction, tMax);\n"
201 		<< "    while (rayQueryProceedEXT(rq)) {\n"
202 		<< "      if (rayQueryGetIntersectionTypeEXT(rq, false) == gl_RayQueryCandidateIntersectionTriangleEXT) {\n"
203 		<< "        vec3 outputVal[3];\n"
204 		<< "        rayQueryGetIntersectionTriangleVertexPositionsEXT(rq, false, outputVal);\n"
205 		<< "        for (int i=0; i<3; i++) {\n"
206 		<< "           modes.values[3*index.x+i] = vec4(outputVal[i], 0);\n"
207 //		<< "           modes.values[3*index.x+i] = vec4(1.0, 1.0, 1.0, 0);\n"
208 		<< "        }\n"
209 		<< "      }\n"
210 		<< "    }\n"
211 		<< "    index += " << kNumThreadsAtOnce << ";\n"
212 		<< "  }\n";
213 
214 	if (m_params.shaderSourceType == SST_VERTEX_SHADER) {
215 		std::ostringstream vert;
216 		vert
217 			<< sharedHeader.str()
218 			<< "void main()\n"
219 			<< "{\n"
220 			<< "  uint index             = gl_VertexIndex.x;\n"
221 			<< mainLoop.str()
222 			<< "}\n"
223 			;
224 
225 		programCollection.glslSources.add("vert") << glu::VertexSource(vert.str()) << buildOptions;
226 	}
227 	else if (m_params.shaderSourceType == SST_RAY_GENERATION_SHADER)
228 	{
229 		std::ostringstream rgen;
230 		rgen
231 			<< sharedHeader.str()
232 			<< "#extension GL_EXT_ray_tracing : require\n"
233 			<< "void main()\n"
234 			<< "{\n"
235 			<< "  uint index             = gl_LaunchIDEXT.x;\n"
236 			<< mainLoop.str()
237 			<< "}\n"
238 			;
239 
240 		programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(rgen.str())) << buildOptions;
241 	}
242 	else
243 	{
244 		DE_ASSERT(m_params.shaderSourceType == SST_COMPUTE_SHADER);
245 		std::ostringstream comp;
246 		comp
247 			<< sharedHeader.str()
248 			<< "layout(local_size_x=1024, local_size_y=1, local_size_z=1) in;\n"
249 			<< "\n"
250 			<< "void main()\n"
251 			<< "{\n"
252 			<< "  uint index             = gl_LocalInvocationID.x;\n"
253 			<< mainLoop.str()
254 			<< "}\n"
255 			;
256 
257 		programCollection.glslSources.add("comp") << glu::ComputeSource(updateRayTracingGLSL(comp.str())) << buildOptions;
258 	}
259 }
260 
createInstance(Context & context) const261 TestInstance* PositionFetchCase::createInstance (Context& context) const
262 {
263 	return new PositionFetchInstance(context, m_params);
264 }
265 
PositionFetchInstance(Context & context,const TestParams & params)266 PositionFetchInstance::PositionFetchInstance (Context& context, const TestParams& params)
267 	: TestInstance	(context)
268 	, m_params		(params)
269 {}
270 
makeEmptyRenderPass(const DeviceInterface & vk,const VkDevice device)271 static Move<VkRenderPass> makeEmptyRenderPass(const DeviceInterface& vk,
272 	const VkDevice				device)
273 {
274 	std::vector<VkSubpassDescription>	subpassDescriptions;
275 
276 	const VkSubpassDescription	description =
277 	{
278 		(VkSubpassDescriptionFlags)0,		//  VkSubpassDescriptionFlags		flags;
279 		VK_PIPELINE_BIND_POINT_GRAPHICS,	//  VkPipelineBindPoint				pipelineBindPoint;
280 		0u,									//  deUint32						inputAttachmentCount;
281 		DE_NULL,							//  const VkAttachmentReference*	pInputAttachments;
282 		0u,									//  deUint32						colorAttachmentCount;
283 		DE_NULL,							//  const VkAttachmentReference*	pColorAttachments;
284 		DE_NULL,							//  const VkAttachmentReference*	pResolveAttachments;
285 		DE_NULL,							//  const VkAttachmentReference*	pDepthStencilAttachment;
286 		0,									//  deUint32						preserveAttachmentCount;
287 		DE_NULL								//  const deUint32*					pPreserveAttachments;
288 	};
289 	subpassDescriptions.push_back(description);
290 
291 	const VkRenderPassCreateInfo renderPassInfo =
292 	{
293 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,							//  VkStructureType					sType;
294 		DE_NULL,															//  const void*						pNext;
295 		static_cast<VkRenderPassCreateFlags>(0u),							//  VkRenderPassCreateFlags			flags;
296 		0u,																	//  deUint32						attachmentCount;
297 		DE_NULL,															//  const VkAttachmentDescription*	pAttachments;
298 		static_cast<deUint32>(subpassDescriptions.size()),					//  deUint32						subpassCount;
299 		&subpassDescriptions[0],											//  const VkSubpassDescription*		pSubpasses;
300 		0u,																	//  deUint32						dependencyCount;
301 		DE_NULL																//  const VkSubpassDependency*		pDependencies;
302 	};
303 
304 	return createRenderPass(vk, device, &renderPassInfo);
305 }
306 
makeFramebuffer(const DeviceInterface & vk,const VkDevice device,VkRenderPass renderPass,uint32_t width,uint32_t height)307 static Move<VkFramebuffer> makeFramebuffer (const DeviceInterface& vk, const VkDevice device, VkRenderPass renderPass, uint32_t width, uint32_t height)
308 {
309 	const vk::VkFramebufferCreateInfo	framebufferParams =
310 	{
311 		vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,					// sType
312 		DE_NULL,														// pNext
313 		(vk::VkFramebufferCreateFlags)0,
314 		renderPass,														// renderPass
315 		0u,																// attachmentCount
316 		DE_NULL,														// pAttachments
317 		width,															// width
318 		height,															// height
319 		1u,																// layers
320 	};
321 
322 	return createFramebuffer(vk, device, &framebufferParams);
323 }
324 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const deUint32 subpass)325 Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface& vk,
326 	const VkDevice				device,
327 	const VkPipelineLayout		pipelineLayout,
328 	const VkRenderPass			renderPass,
329 	const VkShaderModule		vertexModule,
330 	const deUint32				subpass)
331 {
332 	VkExtent2D												renderSize { 256, 256 };
333 	VkViewport												viewport = makeViewport(renderSize);
334 	VkRect2D												scissor = makeRect2D(renderSize);
335 
336 	const VkPipelineViewportStateCreateInfo					viewportStateCreateInfo =
337 	{
338 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,		// VkStructureType                             sType
339 		DE_NULL,													// const void*                                 pNext
340 		(VkPipelineViewportStateCreateFlags)0,						// VkPipelineViewportStateCreateFlags          flags
341 		1u,															// deUint32                                    viewportCount
342 		&viewport,													// const VkViewport*                           pViewports
343 		1u,															// deUint32                                    scissorCount
344 		&scissor													// const VkRect2D*                             pScissors
345 	};
346 
347 	const VkPipelineInputAssemblyStateCreateInfo			inputAssemblyStateCreateInfo =
348 	{
349 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                            sType
350 		DE_NULL,														// const void*                                pNext
351 		0u,																// VkPipelineInputAssemblyStateCreateFlags    flags
352 		VK_PRIMITIVE_TOPOLOGY_POINT_LIST,								// VkPrimitiveTopology                        topology
353 		VK_FALSE														// VkBool32                                   primitiveRestartEnable
354 	};
355 
356 	const VkPipelineVertexInputStateCreateInfo				vertexInputStateCreateInfo =
357 	{
358 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,									//  VkStructureType									sType
359 		DE_NULL,																					//  const void*										pNext
360 		(VkPipelineVertexInputStateCreateFlags)0,													//  VkPipelineVertexInputStateCreateFlags			flags
361 		0u,																							//  deUint32										vertexBindingDescriptionCount
362 		DE_NULL,																					//  const VkVertexInputBindingDescription*			pVertexBindingDescriptions
363 		0u,																							//  deUint32										vertexAttributeDescriptionCount
364 		DE_NULL,																					//  const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions
365 	};
366 
367 	const VkPipelineRasterizationStateCreateInfo			rasterizationStateCreateInfo =
368 	{
369 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//  VkStructureType							sType
370 		DE_NULL,													//  const void*								pNext
371 		0u,															//  VkPipelineRasterizationStateCreateFlags	flags
372 		VK_FALSE,													//  VkBool32								depthClampEnable
373 		VK_TRUE,													//  VkBool32								rasterizerDiscardEnable
374 		VK_POLYGON_MODE_FILL,										//  VkPolygonMode							polygonMode
375 		VK_CULL_MODE_NONE,											//  VkCullModeFlags							cullMode
376 		VK_FRONT_FACE_COUNTER_CLOCKWISE,							//  VkFrontFace								frontFace
377 		VK_FALSE,													//  VkBool32								depthBiasEnable
378 		0.0f,														//  float									depthBiasConstantFactor
379 		0.0f,														//  float									depthBiasClamp
380 		0.0f,														//  float									depthBiasSlopeFactor
381 		1.0f														//  float									lineWidth
382 	};
383 
384 	return makeGraphicsPipeline(vk,									// const DeviceInterface&							vk
385 		device,								// const VkDevice									device
386 		pipelineLayout,						// const VkPipelineLayout							pipelineLayout
387 		vertexModule,						// const VkShaderModule								vertexShaderModule
388 		DE_NULL,							// const VkShaderModule								tessellationControlModule
389 		DE_NULL,							// const VkShaderModule								tessellationEvalModule
390 		DE_NULL,							// const VkShaderModule								geometryShaderModule
391 		DE_NULL,							// const VkShaderModule								fragmentShaderModule
392 		renderPass,							// const VkRenderPass								renderPass
393 		subpass,							// const deUint32									subpass
394 		&vertexInputStateCreateInfo,		// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
395 		&inputAssemblyStateCreateInfo,		// const VkPipelineInputAssemblyStateCreateInfo*	inputAssemblyStateCreateInfo
396 		DE_NULL,							// const VkPipelineTessellationStateCreateInfo*		tessStateCreateInfo
397 		&viewportStateCreateInfo,			// const VkPipelineViewportStateCreateInfo*			viewportStateCreateInfo
398 		&rasterizationStateCreateInfo);	// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
399 }
400 
iterate(void)401 tcu::TestStatus PositionFetchInstance::iterate (void)
402 {
403 	const auto&	vkd		= m_context.getDeviceInterface();
404 	const auto	device	= m_context.getDevice();
405 	auto&		alloc	= m_context.getDefaultAllocator();
406 	const auto	qIndex	= m_context.getUniversalQueueFamilyIndex();
407 	const auto	queue	= m_context.getUniversalQueue();
408 
409 	// Command pool and buffer.
410 	const auto cmdPool		= makeCommandPool(vkd, device, qIndex);
411 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
412 	const auto cmdBuffer	= cmdBufferPtr.get();
413 
414 	beginCommandBuffer(vkd, cmdBuffer);
415 
416 	// Build acceleration structures.
417 	auto topLevelAS		= makeTopLevelAccelerationStructure();
418 	auto bottomLevelAS	= makeBottomLevelAccelerationStructure();
419 
420 	const std::vector<tcu::Vec3> triangle =
421 	{
422 		tcu::Vec3(0.0f, 0.0f, 0.0f),
423 		tcu::Vec3(1.0f, 0.0f, 0.0f),
424 		tcu::Vec3(0.0f, 1.0f, 0.0f),
425 	};
426 
427 	const VkTransformMatrixKHR notQuiteIdentityMatrix3x4 = { { { 0.98f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.97f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.99f, 0.0f } } };
428 
429 	de::SharedPtr<RaytracedGeometryBase> geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, m_params.vertexFormat, VK_INDEX_TYPE_NONE_KHR);
430 
431 	for (auto & v : triangle) {
432 		geometry->addVertex(v);
433 	}
434 
435 	bottomLevelAS->addGeometry(geometry);
436 	bottomLevelAS->setBuildFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR);
437 	bottomLevelAS->setBuildType(m_params.buildType);
438 	bottomLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
439 	de::SharedPtr<BottomLevelAccelerationStructure> blasSharedPtr (bottomLevelAS.release());
440 
441 	topLevelAS->setInstanceCount(1);
442 	topLevelAS->setBuildType(m_params.buildType);
443 	topLevelAS->addInstance(blasSharedPtr, (m_params.testFlagMask & TEST_FLAG_BIT_INSTANCE_TRANSFORM) ? notQuiteIdentityMatrix3x4 : identityMatrix3x4);
444 	topLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
445 
446 	// One ray for this test
447 	// XXX Should it be multiple triangles and one ray per triangle for more coverage?
448 	// XXX If it's really one ray, the origin buffer is complete overkill
449 	deUint32 numRays = 1; // XXX
450 
451 	// SSBO buffer for origins.
452 	const auto originsBufferSize		= static_cast<VkDeviceSize>(sizeof(tcu::Vec4) * numRays);
453 	const auto originsBufferInfo		= makeBufferCreateInfo(originsBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
454 	BufferWithMemory originsBuffer	(vkd, device, alloc, originsBufferInfo, MemoryRequirement::HostVisible);
455 	auto& originsBufferAlloc			= originsBuffer.getAllocation();
456 	void* originsBufferData				= originsBufferAlloc.getHostPtr();
457 
458 	std::vector<tcu::Vec4> origins;
459 	std::vector<tcu::Vec3> expectedOutputPositions;
460 	origins.reserve(numRays);
461 	expectedOutputPositions.reserve(3*numRays);
462 
463 	// Fill in vector of expected outputs
464 	for (deUint32 index = 0; index < numRays; index++) {
465 		for (deUint32 vert = 0; vert < 3; vert++) {
466 			tcu::Vec3 pos = triangle[vert];
467 
468 			expectedOutputPositions.push_back(pos);
469 		}
470 	}
471 
472 	// XXX Arbitrary location and see above
473 	for (deUint32 index = 0; index < numRays; index++) {
474 		origins.push_back(tcu::Vec4(0.25, 0.25, 1.0, 0.0));
475 	}
476 
477 	const auto				originsBufferSizeSz = static_cast<size_t>(originsBufferSize);
478 	deMemcpy(originsBufferData, origins.data(), originsBufferSizeSz);
479 	flushAlloc(vkd, device, originsBufferAlloc);
480 
481 	// Storage buffer for output modes
482 	const auto outputPositionsBufferSize = static_cast<VkDeviceSize>(3 * 4 * sizeof(float) * numRays);
483 	const auto outputPositionsBufferInfo = makeBufferCreateInfo(outputPositionsBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
484 	BufferWithMemory outputPositionsBuffer(vkd, device, alloc, outputPositionsBufferInfo, MemoryRequirement::HostVisible);
485 	auto& outputPositionsBufferAlloc = outputPositionsBuffer.getAllocation();
486 	void* outputPositionsBufferData = outputPositionsBufferAlloc.getHostPtr();
487 	deMemset(outputPositionsBufferData, 0xFF, static_cast<size_t>(outputPositionsBufferSize));
488 	flushAlloc(vkd, device, outputPositionsBufferAlloc);
489 
490 	// Descriptor set layout.
491 	DescriptorSetLayoutBuilder dsLayoutBuilder;
492 	dsLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_ALL);
493 	dsLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL);
494 	dsLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL);
495 	const auto setLayout = dsLayoutBuilder.build(vkd, device);
496 
497 	// Pipeline layout.
498 	const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
499 
500 	// Descriptor pool and set.
501 	DescriptorPoolBuilder poolBuilder;
502 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
503 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
504 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
505 	const auto descriptorPool	= poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
506 	const auto descriptorSet	= makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
507 
508 	// Update descriptor set.
509 	{
510 		const VkWriteDescriptorSetAccelerationStructureKHR accelDescInfo =
511 		{
512 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
513 			nullptr,
514 			1u,
515 			topLevelAS.get()->getPtr(),
516 		};
517 		const auto inStorageBufferInfo = makeDescriptorBufferInfo(originsBuffer.get(), 0ull, VK_WHOLE_SIZE);
518 		const auto storageBufferInfo = makeDescriptorBufferInfo(outputPositionsBuffer.get(), 0ull, VK_WHOLE_SIZE);
519 
520 		DescriptorSetUpdateBuilder updateBuilder;
521 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelDescInfo);
522 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inStorageBufferInfo);
523 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &storageBufferInfo);
524 		updateBuilder.update(vkd, device);
525 	}
526 
527 	Move<VkPipeline>				pipeline;
528 	de::MovePtr<BufferWithMemory>	raygenSBT;
529 	Move<VkRenderPass>				renderPass;
530 	Move<VkFramebuffer>				framebuffer;
531 
532 	if (m_params.shaderSourceType == SST_VERTEX_SHADER)
533 	{
534 		auto vertexModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0);
535 
536 		const uint32_t width = 32u;
537 		const uint32_t height = 32u;
538 		renderPass = makeEmptyRenderPass(vkd, device);
539 		framebuffer = makeFramebuffer(vkd, device, *renderPass, width, height);
540 		pipeline = makeGraphicsPipeline(vkd, device, *pipelineLayout, *renderPass, *vertexModule, 0);
541 
542 		const VkRenderPassBeginInfo			renderPassBeginInfo =
543 		{
544 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,							// VkStructureType								sType;
545 			DE_NULL,															// const void*									pNext;
546 			*renderPass,														// VkRenderPass									renderPass;
547 			*framebuffer,														// VkFramebuffer								framebuffer;
548 			makeRect2D(width, height),											// VkRect2D										renderArea;
549 			0u,																	// uint32_t										clearValueCount;
550 			DE_NULL																// const VkClearValue*							pClearValues;
551 		};
552 
553 		vkd.cmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
554 		vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
555 		vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
556 		vkd.cmdDraw(cmdBuffer, kNumThreadsAtOnce, 1, 0, 0);
557 		vkd.cmdEndRenderPass(cmdBuffer);
558 	}
559 	else if (m_params.shaderSourceType == SST_RAY_GENERATION_SHADER)
560 	{
561 		const auto& vki = m_context.getInstanceInterface();
562 		const auto	physDev = m_context.getPhysicalDevice();
563 
564 		// Shader module.
565 		auto rgenModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0);
566 
567 		// Get some ray tracing properties.
568 		deUint32 shaderGroupHandleSize = 0u;
569 		deUint32 shaderGroupBaseAlignment = 1u;
570 		{
571 			const auto rayTracingPropertiesKHR = makeRayTracingProperties(vki, physDev);
572 			shaderGroupHandleSize = rayTracingPropertiesKHR->getShaderGroupHandleSize();
573 			shaderGroupBaseAlignment = rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
574 		}
575 
576 		auto raygenSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
577 		auto unusedSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
578 
579 		{
580 			const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
581 			rayTracingPipeline->setCreateFlags(VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT);
582 			rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenModule, 0);
583 
584 			pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout.get());
585 
586 			raygenSBT = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
587 			raygenSBTRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
588 		}
589 
590 		// Trace rays.
591 		vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.get());
592 		vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
593 		vkd.cmdTraceRaysKHR(cmdBuffer, &raygenSBTRegion, &unusedSBTRegion, &unusedSBTRegion, &unusedSBTRegion, kNumThreadsAtOnce, 1u, 1u);
594 	}
595 	else
596 	{
597 		DE_ASSERT(m_params.shaderSourceType == SST_COMPUTE_SHADER);
598 		// Shader module.
599 		const auto compModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("comp"), 0);
600 
601 		// Pipeline.
602 		const VkPipelineShaderStageCreateInfo shaderInfo =
603 		{
604 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	//	VkStructureType						sType;
605 			nullptr,												//	const void*							pNext;
606 			0u,														//	VkPipelineShaderStageCreateFlags	flags;
607 			VK_SHADER_STAGE_COMPUTE_BIT,							//	VkShaderStageFlagBits				stage;
608 			compModule.get(),										//	VkShaderModule						module;
609 			"main",													//	const char*							pName;
610 			nullptr,												//	const VkSpecializationInfo*			pSpecializationInfo;
611 		};
612 		const VkComputePipelineCreateInfo pipelineInfo =
613 		{
614 			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,	//	VkStructureType					sType;
615 			nullptr,										//	const void*						pNext;
616 			0u,												//	VkPipelineCreateFlags			flags;
617 			shaderInfo,										//	VkPipelineShaderStageCreateInfo	stage;
618 			pipelineLayout.get(),							//	VkPipelineLayout				layout;
619 			DE_NULL,										//	VkPipeline						basePipelineHandle;
620 			0,												//	deInt32							basePipelineIndex;
621 		};
622 		pipeline = createComputePipeline(vkd, device, DE_NULL, &pipelineInfo);
623 
624 		// Dispatch work with ray queries.
625 		vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.get());
626 		vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
627 		vkd.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
628 	}
629 
630 	// Barrier for the output buffer.
631 	const auto bufferBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
632 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &bufferBarrier, 0u, nullptr, 0u, nullptr);
633 
634 	endCommandBuffer(vkd, cmdBuffer);
635 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
636 
637 	// Verify results.
638 	std::vector<tcu::Vec4>	outputData(expectedOutputPositions.size());
639 	const auto				outputPositionsBufferSizeSz = static_cast<size_t>(outputPositionsBufferSize);
640 
641 	invalidateAlloc(vkd, device, outputPositionsBufferAlloc);
642 	DE_ASSERT(de::dataSize(outputData) == outputPositionsBufferSizeSz);
643 	deMemcpy(outputData.data(), outputPositionsBufferData, outputPositionsBufferSizeSz);
644 
645 	for (size_t i = 0; i < outputData.size(); ++i)
646 	{
647 		/*const */ auto& outVal = outputData[i]; // Should be const but .xyz() isn't
648 		tcu::Vec3 outVec3 = outVal.xyz();
649 		const auto& expectedVal = expectedOutputPositions[i];
650 		const auto& diff = expectedOutputPositions[i] - outVec3;
651 		float len = dot(diff, diff);
652 
653 		// XXX Find a better epsilon
654 		if (!(len < 1e-5))
655 		{
656 			std::ostringstream msg;
657 			msg << "Unexpected value found for element " << i << ": expected " << expectedVal << " and found " << outVal << ";";
658 			TCU_FAIL(msg.str());
659 		}
660 #if 0
661 		else
662 		{
663 			std::ostringstream msg;
664 			msg << "Expected value found for element " << i << ": expected " << expectedVal << " and found " << outVal << ";\n";
665 			std::cout << msg.str();
666 		}
667 #endif
668 	}
669 
670 	return tcu::TestStatus::pass("Pass");
671 }
672 
673 } // anonymous
674 
createPositionFetchTests(tcu::TestContext & testCtx)675 tcu::TestCaseGroup*	createPositionFetchTests (tcu::TestContext& testCtx)
676 {
677 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "position_fetch"));
678 
679 	struct
680 	{
681 		vk::VkAccelerationStructureBuildTypeKHR				buildType;
682 		const char* name;
683 	} buildTypes[] =
684 	{
685 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
686 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
687 	};
688 
689 
690 	const struct
691 	{
692 		ShaderSourceType						shaderSourceType;
693 		ShaderSourcePipeline					shaderSourcePipeline;
694 		std::string								name;
695 	} shaderSourceTypes[] =
696 	{
697 		{ SST_VERTEX_SHADER,					SSP_GRAPHICS_PIPELINE,		"vertex_shader"				},
698 		{ SST_COMPUTE_SHADER,					SSP_COMPUTE_PIPELINE,		"compute_shader",			},
699 		{ SST_RAY_GENERATION_SHADER,			SSP_RAY_TRACING_PIPELINE,	"rgen_shader",				},
700 	};
701 
702 	const VkFormat vertexFormats[] =
703 	{
704 		// Mandatory formats.
705 		VK_FORMAT_R32G32_SFLOAT,
706 		VK_FORMAT_R32G32B32_SFLOAT,
707 		VK_FORMAT_R16G16_SFLOAT,
708 		VK_FORMAT_R16G16B16A16_SFLOAT,
709 		VK_FORMAT_R16G16_SNORM,
710 		VK_FORMAT_R16G16B16A16_SNORM,
711 
712 		// Additional formats.
713 		VK_FORMAT_R8G8_SNORM,
714 		VK_FORMAT_R8G8B8_SNORM,
715 		VK_FORMAT_R8G8B8A8_SNORM,
716 		VK_FORMAT_R16G16B16_SNORM,
717 		VK_FORMAT_R16G16B16_SFLOAT,
718 		VK_FORMAT_R32G32B32A32_SFLOAT,
719 		VK_FORMAT_R64G64_SFLOAT,
720 		VK_FORMAT_R64G64B64_SFLOAT,
721 		VK_FORMAT_R64G64B64A64_SFLOAT,
722 	};
723 
724 	for (size_t shaderSourceNdx = 0; shaderSourceNdx < DE_LENGTH_OF_ARRAY(shaderSourceTypes); ++shaderSourceNdx)
725 	{
726 		de::MovePtr<tcu::TestCaseGroup> sourceTypeGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderSourceTypes[shaderSourceNdx].name.c_str()));
727 
728 		for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
729 		{
730 			de::MovePtr<tcu::TestCaseGroup> buildGroup(new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
731 
732 			for (size_t vertexFormatNdx = 0; vertexFormatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); ++vertexFormatNdx)
733 			{
734 				const auto format = vertexFormats[vertexFormatNdx];
735 				const auto formatName = getFormatSimpleName(format);
736 
737 				de::MovePtr<tcu::TestCaseGroup> vertexFormatGroup(new tcu::TestCaseGroup(group->getTestContext(), formatName.c_str()));
738 
739 				for (deUint32 testFlagMask = 0; testFlagMask < TEST_FLAG_BIT_LAST; testFlagMask++)
740 				{
741 					std::string maskName = "";
742 
743 					for (deUint32 bit = 0; bit < testFlagBitNames.size(); bit++)
744 					{
745 						if (testFlagMask & (1 << bit))
746 						{
747 							if (maskName != "")
748 								maskName += "_";
749 							maskName += testFlagBitNames[bit];
750 						}
751 					}
752 					if (maskName == "")
753 						maskName = "NoFlags";
754 
755 					de::MovePtr<tcu::TestCaseGroup> testFlagGroup(new tcu::TestCaseGroup(group->getTestContext(), maskName.c_str()));
756 
757 					TestParams testParams
758 					{
759 						shaderSourceTypes[shaderSourceNdx].shaderSourceType,
760 						shaderSourceTypes[shaderSourceNdx].shaderSourcePipeline,
761 						buildTypes[buildTypeNdx].buildType,
762 						format,
763 						testFlagMask,
764 					};
765 
766 					vertexFormatGroup->addChild(new PositionFetchCase(testCtx, maskName, testParams));
767 				}
768 				buildGroup->addChild(vertexFormatGroup.release());
769 			}
770 			sourceTypeGroup->addChild(buildGroup.release());
771 		}
772 		group->addChild(sourceTypeGroup.release());
773 	}
774 
775 	return group.release();
776 }
777 } // RayQuery
778 } // vkt
779