Browse Source

Start writing the unit test

Panagiotis Christopoulos Charitos 5 years ago
parent
commit
0c3e3e87ce

+ 5 - 2
src/anki/gr/Common.h

@@ -144,10 +144,13 @@ public:
 
 
 	/// API version.
 	/// API version.
 	U8 m_majorApiVersion = 0;
 	U8 m_majorApiVersion = 0;
+
+	/// RT.
+	Bool m_rayTracingEnabled = false;
 };
 };
 ANKI_END_PACKED_STRUCT
 ANKI_END_PACKED_STRUCT
-static_assert(
-	sizeof(GpuDeviceCapabilities) == sizeof(PtrSize) * 4 + sizeof(U32) * 3 + sizeof(U8) * 3, "Should be packed");
+static_assert(sizeof(GpuDeviceCapabilities) == sizeof(PtrSize) * 4 + sizeof(U32) * 3 + sizeof(U8) * 3 + sizeof(Bool),
+	"Should be packed");
 
 
 /// Bindless related info.
 /// Bindless related info.
 class BindlessLimits
 class BindlessLimits

+ 3 - 2
src/anki/gr/Enums.h

@@ -665,8 +665,9 @@ enum class AccelerationStructureUsageBit : U8
 {
 {
 	NONE = 0,
 	NONE = 0,
 	BUILD = 1 << 0,
 	BUILD = 1 << 0,
-	COMPUTE_READ = 1 << 1,
-	RAY_GEN_READ = 1 << 2
+	ATTACH = 1 << 1, ///< Attached to a TLAS. Only for BLAS.
+	COMPUTE_READ = 1 << 2,
+	RAY_GEN_READ = 1 << 3
 };
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(AccelerationStructureUsageBit, inline)
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(AccelerationStructureUsageBit, inline)
 /// @}
 /// @}

+ 6 - 0
src/anki/gr/vulkan/AccelerationStructureImpl.cpp

@@ -257,6 +257,12 @@ void AccelerationStructureImpl::computeBarrierInfo(AccelerationStructureUsageBit
 	dstStages = 0;
 	dstStages = 0;
 	dstAccesses = 0;
 	dstAccesses = 0;
 
 
+	if(!!(after & AccelerationStructureUsageBit::ATTACH))
+	{
+		dstStages |= VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR;
+		dstAccesses |= VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
+	}
+
 	if(!!(after & AccelerationStructureUsageBit::COMPUTE_READ))
 	if(!!(after & AccelerationStructureUsageBit::COMPUTE_READ))
 	{
 	{
 		dstStages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
 		dstStages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;

+ 1 - 0
src/anki/gr/vulkan/GrManagerImpl.cpp

@@ -535,6 +535,7 @@ Error GrManagerImpl::initDevice(const GrManagerInitInfo& init)
 			{
 			{
 				m_extensions |= VulkanExtensions::KHR_RAY_TRACING;
 				m_extensions |= VulkanExtensions::KHR_RAY_TRACING;
 				extensionsToEnable[extensionsToEnableCount++] = VK_KHR_RAY_TRACING_EXTENSION_NAME;
 				extensionsToEnable[extensionsToEnableCount++] = VK_KHR_RAY_TRACING_EXTENSION_NAME;
+				m_capabilities.m_rayTracingEnabled = true;
 			}
 			}
 		}
 		}
 
 

+ 150 - 0
tests/gr/Gr.cpp

@@ -2459,4 +2459,154 @@ void main()
 	COMMON_END();
 	COMMON_END();
 }
 }
 
 
+ANKI_TEST(Gr, AccelerationStructure)
+{
+	COMMON_BEGIN();
+
+	if(!gr->getDeviceCapabilities().m_rayTracingEnabled)
+	{
+		ANKI_TEST_LOGW("Skipping test since the GPU doesn't support ray tracing");
+	}
+
+	// Index buffer
+	BufferPtr idxBuffer;
+	{
+		Array<U16, 3> indices{0, 1, 2};
+		BufferInitInfo init;
+		init.m_access = BufferMapAccessBit::WRITE;
+		init.m_exposeGpuAddress = true;
+		init.m_size = sizeof(indices);
+		idxBuffer = gr->newBuffer(init);
+
+		void* addr = idxBuffer->map(0, MAX_PTR_SIZE, BufferMapAccessBit::WRITE);
+		memcpy(addr, &indices[0], sizeof(indices));
+		idxBuffer->unmap();
+	}
+
+	// Position buffer (add some padding to complicate things a bit)
+	BufferPtr vertBuffer;
+	{
+		Array<Vec4, 3> verts{{{-1.0f, -1.0f, 0.0f, 100.0f}, {1.0f, 1.0f, 0.0f, 100.0f}, {0.0f, 1.0f, 0.0f, 100.0f}}};
+
+		BufferInitInfo init;
+		init.m_access = BufferMapAccessBit::WRITE;
+		init.m_exposeGpuAddress = true;
+		init.m_size = sizeof(verts);
+		vertBuffer = gr->newBuffer(init);
+
+		void* addr = vertBuffer->map(0, MAX_PTR_SIZE, BufferMapAccessBit::WRITE);
+		memcpy(addr, &verts[0], sizeof(verts));
+		vertBuffer->unmap();
+	}
+
+	// BLAS
+	AccelerationStructurePtr blas;
+	{
+		AccelerationStructureInitInfo init;
+		init.m_type = AccelerationStructureType::BOTTOM_LEVEL;
+		init.m_bottomLevel.m_indexBuffer = idxBuffer;
+		init.m_bottomLevel.m_indexCount = 3;
+		init.m_bottomLevel.m_indexType = IndexType::U16;
+		init.m_bottomLevel.m_positionBuffer = vertBuffer;
+		init.m_bottomLevel.m_positionCount = 3;
+		init.m_bottomLevel.m_positionsFormat = Format::R32G32B32_SFLOAT;
+		init.m_bottomLevel.m_positionStride = 4 * 4;
+
+		blas = gr->newAccelerationStructure(init);
+	}
+
+	// TLAS
+	AccelerationStructurePtr tlas;
+	{
+		AccelerationStructureInitInfo init;
+		init.m_type = AccelerationStructureType::TOP_LEVEL;
+		Array<AccelerationStructureInstance, 1> instances{{{blas, Mat3x4::getIdentity()}}};
+		init.m_topLevel.m_instances = instances;
+
+		tlas = gr->newAccelerationStructure(init);
+	}
+
+	// Program
+	ShaderProgramPtr prog;
+	{
+		CString src = R"(
+#extension GL_EXT_ray_query : enable
+
+layout(local_size_x = 8, local_size_y = 8) in;
+
+layout(push_constant, std140, row_major) uniform b_pc
+{
+	Mat4 u_vp;
+	Vec3 u_cameraPos;
+	F32 u_padding0;
+};
+
+layout(set = 0, binding = 0) uniform accelerationStructureEXT u_tlas;
+
+layout(set = 0, binding = 1, rgba8) writeonly uniform image2D u_outImg;
+
+void main()
+{
+	// Unproject
+	const Vec4 p4 = inverse(u_vp) * Vec4(Vec2(gl_GlobalInvocationID.xy), 0.0, 1.0);
+	const Vec4 p3 = p4.xyz / p4.w;
+
+	const Vec3 rayDir = p3 - u_cameraPos;
+	const Vec3 rayOrigin = u_cameraPos;
+
+	rayQueryEXT rayQuery;
+	rayQueryInitializeEXT(rayQuery, u_tlas, gl_RayFlagsOpaqueEXT | gl_RayFlagsTerminateOnFirstHitEXT, 0xFFu, rayOrigin,
+		0.01, raydir, 1000.0);
+
+	rayQueryProceedEXT(rayQuery);
+
+	Vec3 outColor;
+	U32 committedStatus = rayQueryGetIntersectionTypeEXT(rayQuery);
+	if(committedStatus == gl_RayQueryCommittedIntersectionTriangleEXT)
+	{
+		outColor = Vec3(rayQueryGetIntersectionBarycentricsEXT(rayQuery, true), 0.0);
+	}
+	else
+	{
+		outColor = Vec3(0.0);
+	}
+
+	imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), Vec4(outColor, 0.0));
+}
+		)";
+
+		ShaderPtr shader = createShader(src, ShaderType::COMPUTE, *gr);
+		ShaderProgramInitInfo sprogInit;
+		sprogInit.m_shaders[ShaderType::COMPUTE] = shader;
+		prog = gr->newShaderProgram(sprogInit);
+	}
+
+	// Out buffer
+	constexpr U32 DIMENSION_SIZE = 1024;
+	BufferPtr outBuff;
+	{
+		BufferInitInfo init;
+		init.m_access = BufferMapAccessBit::READ;
+		init.m_usage = BufferUsageBit::STORAGE_ALL;
+		init.m_exposeGpuAddress = false;
+		init.m_size = DIMENSION_SIZE * DIMENSION_SIZE * sizeof(U8) * 3;
+		outBuff = gr->newBuffer(init);
+	}
+
+	// Do the work
+	{
+		CommandBufferInitInfo cinit;
+		cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH;
+		CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
+
+		cmdb->setAccelerationStructureBarrier(
+			blas, AccelerationStructureUsageBit::NONE, AccelerationStructureUsageBit::BUILD);
+		cmdb->buildAccelerationStructure(blas);
+		cmdb->setAccelerationStructureBarrier(
+			blas, AccelerationStructureUsageBit::BUILD, AccelerationStructureUsageBit::ATTACH);
+	}
+
+	COMMON_END();
+}
+
 } // end namespace anki
 } // end namespace anki