mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-25 13:00:09 +01:00
GRL, or Graphics Library for Ray-tracing is a library we share with the Windows drivers for doing BVH builds on the GPU. It consists of a few headers shared between CL and C code, a bunch of CL kernels, and some GRL meta-kernels in their own format. Acked-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Acked-by: Caio Oliveira <caio.oliveira@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16970>
208 lines
6.5 KiB
C
208 lines
6.5 KiB
C
//
|
|
// Copyright (C) 2009-2021 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
//
|
|
//
|
|
|
|
// @file bvh_debug.cl
|
|
//
|
|
// @brief routines to do basic integrity checks
|
|
//
|
|
// Notes:
|
|
//
|
|
|
|
#include "GRLGen12.h"
|
|
#include "intrinsics.h"
|
|
#include "libs/lsc_intrinsics.h"
|
|
#include "GRLGen12IntegrityChecks.h"
|
|
#include "api_interface.h"
|
|
|
|
#define ERROR_PRINTF 0
|
|
GRL_INLINE bool commit_err(
|
|
global uint* some_null,
|
|
global BVHBase* bvh,
|
|
global ERROR_INFO* err_info_slot,
|
|
ERROR_INFO err)
|
|
{
|
|
if (err.type != error_t_no_error) {
|
|
uint expected = error_t_no_error;
|
|
atomic_compare_exchange_global(&err_info_slot->type, &expected, err.type);
|
|
if (expected == error_t_no_error)
|
|
{
|
|
err_info_slot->offset_in_BVH = err.offset_in_BVH;
|
|
err_info_slot->when = err.when;
|
|
err_info_slot->reserved = 0xAAACCAAA;
|
|
mem_fence_evict_to_memory();
|
|
#if ERROR_PRINTF
|
|
printf("bvh = 0x%llX, err.type = %X, err.offset_in_BVH = %d\n", bvh, err.type, err.offset_in_BVH);
|
|
#else
|
|
// This is to trigger PF. Note we have to write directly to memory.
|
|
// If write would stay in L3 it won't give a PF untill this will get evicted to mem.
|
|
store_uint_L1UC_L3UC(some_null, 0, 0x0EEE0000 + err.type);
|
|
#endif
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
__attribute__((reqd_work_group_size(16, 1, 1)))
|
|
void kernel check_tree_topology(
|
|
global uint* some_null,
|
|
global BVHBase* bvh,
|
|
global ERROR_INFO* err,
|
|
uint phase)
|
|
{
|
|
uint globalID = get_local_id(0) + get_group_id(0) * get_local_size(0);
|
|
|
|
if (err->type != error_t_no_error) return;
|
|
|
|
uint dummy1, dummy2, dummy3;
|
|
ERROR_INFO reterr = check_tree_topology_helper(bvh, globalID, &dummy1, &dummy2, &dummy3, false);
|
|
if (reterr.type == error_t_no_error)
|
|
{
|
|
reterr = check_backpointers(bvh, globalID);
|
|
}
|
|
if (reterr.type == error_t_no_error)
|
|
{
|
|
reterr = validate_atomic_update_structs(bvh, globalID);
|
|
}
|
|
reterr.when = phase;
|
|
commit_err(some_null, bvh, err, reterr);
|
|
}
|
|
|
|
GRL_INLINE bool IsValid48bPtr(qword ptr)
|
|
{
|
|
qword CANONIZED_BITS = 0xFFFFul << 48ul;
|
|
qword canonized_part = ptr & CANONIZED_BITS;
|
|
bool isIt = ptr != 0 && (
|
|
canonized_part == 0 || canonized_part == CANONIZED_BITS);
|
|
return isIt;
|
|
}
|
|
|
|
__attribute__((reqd_work_group_size(16, 1, 1)))
|
|
void kernel check_geos_before_quad_update(
|
|
global BVHBase* bvh, //dest bvh
|
|
global GRL_RAYTRACING_GEOMETRY_DESC* geomDesc,
|
|
global uint* some_null,
|
|
global ERROR_INFO* err,
|
|
uint phase,
|
|
uint numGeos,
|
|
uint numThreads)
|
|
{
|
|
uint globalID = get_local_id(0) + get_group_id(0) * get_local_size(0);
|
|
|
|
if (err->type != error_t_no_error) return;
|
|
|
|
// first check sanity of geos
|
|
ERROR_INFO geo_insanity_error = { error_t_input_geo_insane, 0 };
|
|
|
|
for (uint ID = globalID; ID < numGeos; ID += numThreads * get_sub_group_size())
|
|
{
|
|
bool IsSane = IsValid48bPtr((qword)(qword)geomDesc);
|
|
|
|
if (IsSane) {
|
|
GRL_RAYTRACING_GEOMETRY_DESC geo = geomDesc[globalID];
|
|
IsSane = geo.Type < NUM_GEOMETRY_TYPES;
|
|
if (IsSane) {
|
|
if (geo.Type == GEOMETRY_TYPE_TRIANGLES) {
|
|
if (geo.Desc.Triangles.IndexFormat >= INDEX_FORMAT_END) {
|
|
IsSane = false;
|
|
}
|
|
else
|
|
{
|
|
if (geo.Desc.Triangles.IndexFormat != INDEX_FORMAT_NONE && geo.Desc.Triangles.IndexCount > 2)
|
|
{
|
|
IsSane = (geo.Desc.Triangles.VertexFormat < VERTEX_FORMAT_END) &&
|
|
IsValid48bPtr((qword)geo.Desc.Triangles.pVertexBuffer) &&
|
|
IsValid48bPtr((qword)geo.Desc.Triangles.pIndexBuffer);
|
|
}
|
|
else if (geo.Desc.Triangles.VertexCount > 2)
|
|
{
|
|
IsSane =
|
|
geo.Desc.Triangles.VertexFormat < VERTEX_FORMAT_END&&
|
|
IsValid48bPtr((qword)geo.Desc.Triangles.pVertexBuffer) != 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
geo_insanity_error.offset_in_BVH = ID;
|
|
geo_insanity_error.when = phase;
|
|
if (!IsSane) {
|
|
commit_err(some_null, bvh, err, geo_insanity_error);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
__attribute__((reqd_work_group_size(16, 1, 1)))
|
|
void kernel check_geos_vs_quads(
|
|
global BVHBase* bvh,
|
|
global GRL_RAYTRACING_GEOMETRY_DESC* geomDesc,
|
|
global uint* some_null,
|
|
global ERROR_INFO* err,
|
|
uint phase,
|
|
uint numGeos,
|
|
uint numThreads)
|
|
{
|
|
uint numQuads = BVHBase_GetNumQuads(bvh);
|
|
|
|
QuadLeaf* quads = BVHBase_GetQuadLeaves(bvh);
|
|
|
|
uint globalID = get_local_id(0) + get_group_id(0) * get_local_size(0);
|
|
uint qoffset = bvh->quadLeafStart;
|
|
|
|
if (err->type != error_t_no_error) return;
|
|
|
|
ERROR_INFO theErr = { error_t_no_error, 0 };
|
|
|
|
for (uint ID = globalID; ID < numQuads; ID += numThreads * get_sub_group_size())
|
|
{
|
|
ERROR_INFO quadErr = { error_t_quad_leaf_broken, qoffset + ID, phase };
|
|
|
|
QuadLeaf quad = quads[ID];
|
|
|
|
uint geoIdx = PrimLeaf_GetGeoIndex(&quad.leafDesc);
|
|
|
|
if (geoIdx > numGeos) { commit_err(some_null, bvh, err, quadErr); return; }
|
|
|
|
uint numPrimsInGeo = geomDesc[geoIdx].Desc.Triangles.IndexFormat != INDEX_FORMAT_NONE ?
|
|
geomDesc[geoIdx].Desc.Triangles.IndexCount / 3 :
|
|
geomDesc[geoIdx].Desc.Triangles.VertexCount / 3;
|
|
|
|
if(quad.primIndex0 >= numPrimsInGeo) {
|
|
commit_err(some_null, bvh, err, quadErr);
|
|
return;
|
|
}
|
|
|
|
if(!QuadLeaf_IsSingleTriangle(&quad) &&
|
|
(quad.primIndex0 + QuadLeaf_GetPrimIndexDelta(&quad) >= numPrimsInGeo))
|
|
{
|
|
commit_err(some_null, bvh, err, quadErr);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
__attribute__((reqd_work_group_size(16, 1, 1)))
|
|
void kernel check_instances_linked_bvhs(
|
|
global uint* some_null,
|
|
global BVHBase* bvh,
|
|
global ERROR_INFO* err,
|
|
uint phase)
|
|
{
|
|
if (err->type != error_t_no_error) return;
|
|
|
|
uint instanceLeafStart = bvh->instanceLeafStart;
|
|
uint instanceLeafEnd = bvh->instanceLeafEnd;
|
|
uint numInstances = (instanceLeafEnd - instanceLeafStart) / 2;
|
|
|
|
uint globalID = get_local_id(0) + get_group_id(0) * get_local_size(0);
|
|
|
|
ERROR_INFO reterr = check_instances_linked_bvhs_helper(bvh, globalID, /*touchBlas*/true);
|
|
reterr.when = phase;
|
|
commit_err(some_null, bvh, err, reterr);
|
|
}
|