GLSL: Implement GL_EXT_ray_query.

This commit is contained in:
Hans-Kristian Arntzen 2021-07-19 13:36:37 +02:00
parent 6196e3b029
commit 5b227cc57c
5 changed files with 260 additions and 1 deletions

View File

@ -0,0 +1,52 @@
#version 460
#extension GL_EXT_ray_query : require
#extension GL_EXT_ray_flags_primitive_culling : require
#extension GL_EXT_ray_tracing : require
layout(primitive_culling);
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(set = 0, binding = 1, std140) uniform Params
{
uint ray_flags;
uint cull_mask;
vec3 origin;
float tmin;
vec3 dir;
float tmax;
float thit;
uvec2 bda;
} _19;
layout(set = 0, binding = 0) uniform accelerationStructureEXT AS;
rayQueryEXT q;
rayQueryEXT q2[2];
void main()
{
rayQueryInitializeEXT(q, AS, _19.ray_flags, _19.cull_mask, _19.origin, _19.tmin, _19.dir, _19.tmax);
rayQueryInitializeEXT(q2[1], accelerationStructureEXT(_19.bda), _19.ray_flags, _19.cull_mask, _19.origin, _19.tmin, _19.dir, _19.tmax);
bool _67 = rayQueryProceedEXT(q);
rayQueryTerminateEXT(q2[0]);
rayQueryGenerateIntersectionEXT(q, _19.thit);
rayQueryConfirmIntersectionEXT(q2[1]);
float _75 = rayQueryGetRayTMinEXT(q);
uint _79 = rayQueryGetRayFlagsEXT(q2[0]);
vec3 _82 = rayQueryGetWorldRayDirectionEXT(q);
vec3 _83 = rayQueryGetWorldRayOriginEXT(q);
uint _86 = rayQueryGetIntersectionTypeEXT(q2[1], bool(1));
bool _88 = rayQueryGetIntersectionCandidateAABBOpaqueEXT(q2[1]);
float _91 = rayQueryGetIntersectionTEXT(q2[1], bool(0));
int _94 = rayQueryGetIntersectionInstanceCustomIndexEXT(q, bool(1));
int _96 = rayQueryGetIntersectionInstanceIdEXT(q2[0], bool(0));
uint _97 = rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT(q, bool(1));
int _99 = rayQueryGetIntersectionGeometryIndexEXT(q2[1], bool(0));
int _100 = rayQueryGetIntersectionPrimitiveIndexEXT(q, bool(1));
vec2 _103 = rayQueryGetIntersectionBarycentricsEXT(q2[0], bool(0));
bool _106 = rayQueryGetIntersectionFrontFaceEXT(q, bool(1));
vec3 _107 = rayQueryGetIntersectionObjectRayDirectionEXT(q, bool(0));
vec3 _109 = rayQueryGetIntersectionObjectRayOriginEXT(q2[0], bool(1));
mat4x3 _113 = rayQueryGetIntersectionObjectToWorldEXT(q, bool(0));
mat4x3 _115 = rayQueryGetIntersectionWorldToObjectEXT(q2[1], bool(1));
}

View File

@ -0,0 +1,71 @@
#version 460
#extension GL_EXT_ray_query : require
#extension GL_EXT_ray_flags_primitive_culling : require
#extension GL_EXT_ray_tracing : require
layout(primitive_culling);
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(set = 0, binding = 1, std140) uniform Params
{
uint ray_flags;
uint cull_mask;
vec3 origin;
float tmin;
vec3 dir;
float tmax;
float thit;
uvec2 bda;
} _19;
layout(set = 0, binding = 0) uniform accelerationStructureEXT AS;
rayQueryEXT q;
rayQueryEXT q2[2];
void main()
{
rayQueryInitializeEXT(q, AS, _19.ray_flags, _19.cull_mask, _19.origin, _19.tmin, _19.dir, _19.tmax);
rayQueryInitializeEXT(q2[1], accelerationStructureEXT(_19.bda), _19.ray_flags, _19.cull_mask, _19.origin, _19.tmin, _19.dir, _19.tmax);
bool _67 = rayQueryProceedEXT(q);
bool res = _67;
rayQueryTerminateEXT(q2[0]);
rayQueryGenerateIntersectionEXT(q, _19.thit);
rayQueryConfirmIntersectionEXT(q2[1]);
float _75 = rayQueryGetRayTMinEXT(q);
float fval = _75;
uint _79 = rayQueryGetRayFlagsEXT(q2[0]);
uint type = _79;
vec3 _82 = rayQueryGetWorldRayDirectionEXT(q);
vec3 fvals = _82;
vec3 _83 = rayQueryGetWorldRayOriginEXT(q);
fvals = _83;
uint _86 = rayQueryGetIntersectionTypeEXT(q2[1], bool(1));
type = _86;
bool _88 = rayQueryGetIntersectionCandidateAABBOpaqueEXT(q2[1]);
res = _88;
float _91 = rayQueryGetIntersectionTEXT(q2[1], bool(0));
fval = _91;
int _94 = rayQueryGetIntersectionInstanceCustomIndexEXT(q, bool(1));
int ival = _94;
int _96 = rayQueryGetIntersectionInstanceIdEXT(q2[0], bool(0));
ival = _96;
uint _97 = rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT(q, bool(1));
type = _97;
int _99 = rayQueryGetIntersectionGeometryIndexEXT(q2[1], bool(0));
ival = _99;
int _100 = rayQueryGetIntersectionPrimitiveIndexEXT(q, bool(1));
ival = _100;
vec2 _103 = rayQueryGetIntersectionBarycentricsEXT(q2[0], bool(0));
fvals = vec3(_103.x, _103.y, fvals.z);
bool _106 = rayQueryGetIntersectionFrontFaceEXT(q, bool(1));
res = _106;
vec3 _107 = rayQueryGetIntersectionObjectRayDirectionEXT(q, bool(0));
fvals = _107;
vec3 _109 = rayQueryGetIntersectionObjectRayOriginEXT(q2[0], bool(1));
fvals = _109;
mat4x3 _113 = rayQueryGetIntersectionObjectToWorldEXT(q, bool(0));
mat4x3 matrices = _113;
mat4x3 _115 = rayQueryGetIntersectionWorldToObjectEXT(q2[1], bool(1));
matrices = _115;
}

View File

@ -0,0 +1,58 @@
#version 460
#extension GL_EXT_ray_query : require
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_ray_flags_primitive_culling : require
layout(primitive_culling);
layout(set = 0, binding = 0) uniform accelerationStructureEXT AS;
layout(set = 0, binding = 1) uniform Params
{
uint ray_flags;
uint cull_mask;
vec3 origin;
float tmin;
vec3 dir;
float tmax;
float thit;
uvec2 bda;
};
rayQueryEXT q2[2];
void main()
{
rayQueryEXT q;
bool res;
uint type;
float fval;
vec3 fvals;
int ival;
mat4x3 matrices;
rayQueryInitializeEXT(q, AS, ray_flags, cull_mask, origin, tmin, dir, tmax);
rayQueryInitializeEXT(q2[1], accelerationStructureEXT(bda), ray_flags, cull_mask, origin, tmin, dir, tmax);
res = rayQueryProceedEXT(q);
rayQueryTerminateEXT(q2[0]);
rayQueryGenerateIntersectionEXT(q, thit);
rayQueryConfirmIntersectionEXT(q2[1]);
fval = rayQueryGetRayTMinEXT(q);
type = rayQueryGetRayFlagsEXT(q2[0]);
fvals = rayQueryGetWorldRayDirectionEXT(q);
fvals = rayQueryGetWorldRayOriginEXT(q);
type = rayQueryGetIntersectionTypeEXT(q2[1], true);
res = rayQueryGetIntersectionCandidateAABBOpaqueEXT(q2[1]);
fval = rayQueryGetIntersectionTEXT(q2[1], false);
ival = rayQueryGetIntersectionInstanceCustomIndexEXT(q, true);
ival = rayQueryGetIntersectionInstanceIdEXT(q2[0], false);
type = rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT(q, true);
ival = rayQueryGetIntersectionGeometryIndexEXT(q2[1], false);
ival = rayQueryGetIntersectionPrimitiveIndexEXT(q, true);
fvals.xy = rayQueryGetIntersectionBarycentricsEXT(q2[0], false);
res = rayQueryGetIntersectionFrontFaceEXT(q, true);
fvals = rayQueryGetIntersectionObjectRayDirectionEXT(q, false);
fvals = rayQueryGetIntersectionObjectRayOriginEXT(q2[0], true);
matrices = rayQueryGetIntersectionObjectToWorldEXT(q, false);
matrices = rayQueryGetIntersectionWorldToObjectEXT(q2[1], true);
}

View File

@ -167,6 +167,12 @@ bool Compiler::block_is_pure(const SPIRBlock &block)
case OpTraceRayKHR: case OpTraceRayKHR:
case OpExecuteCallableNV: case OpExecuteCallableNV:
case OpExecuteCallableKHR: case OpExecuteCallableKHR:
case OpRayQueryInitializeKHR:
case OpRayQueryTerminateKHR:
case OpRayQueryGenerateIntersectionKHR:
case OpRayQueryConfirmIntersectionKHR:
case OpRayQueryProceedKHR:
// There are various getters in ray query, but they are considered pure.
return false; return false;
// OpExtInst is potentially impure depending on extension, but GLSL builtins are at least pure. // OpExtInst is potentially impure depending on extension, but GLSL builtins are at least pure.

View File

@ -465,7 +465,8 @@ void CompilerGLSL::find_static_extensions()
// Need to figure out if we should target KHR or NV extension based on capabilities. // Need to figure out if we should target KHR or NV extension based on capabilities.
for (auto &cap : ir.declared_capabilities) for (auto &cap : ir.declared_capabilities)
{ {
if (cap == CapabilityRayTracingKHR || cap == CapabilityRayQueryKHR) if (cap == CapabilityRayTracingKHR || cap == CapabilityRayQueryKHR ||
cap == CapabilityRayTraversalPrimitiveCullingKHR)
{ {
ray_tracing_is_khr = true; ray_tracing_is_khr = true;
break; break;
@ -579,6 +580,20 @@ void CompilerGLSL::find_static_extensions()
} }
break; break;
case CapabilityRayQueryKHR:
if (options.es || options.version < 460 || !options.vulkan_semantics)
SPIRV_CROSS_THROW("RayQuery requires Vulkan GLSL 460.");
require_extension_internal("GL_EXT_ray_query");
ray_tracing_is_khr = true;
break;
case CapabilityRayTraversalPrimitiveCullingKHR:
if (options.es || options.version < 460 || !options.vulkan_semantics)
SPIRV_CROSS_THROW("RayQuery requires Vulkan GLSL 460.");
require_extension_internal("GL_EXT_ray_flags_primitive_culling");
ray_tracing_is_khr = true;
break;
default: default:
break; break;
} }
@ -1061,6 +1076,10 @@ void CompilerGLSL::emit_header()
break; break;
} }
for (auto &cap : ir.declared_capabilities)
if (cap == CapabilityRayTraversalPrimitiveCullingKHR)
statement("layout(primitive_culling);");
if (!inputs.empty()) if (!inputs.empty())
statement("layout(", merge(inputs), ") in;"); statement("layout(", merge(inputs), ") in;");
if (!outputs.empty()) if (!outputs.empty())
@ -12525,7 +12544,57 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
flush_control_dependent_expressions(current_emitting_block->self); flush_control_dependent_expressions(current_emitting_block->self);
break; break;
// Don't bother forwarding temporaries. Avoids having to test expression invalidation with ray query objects.
case OpRayQueryInitializeKHR:
statement("rayQueryInitializeEXT(",
to_expression(ops[0]), ", ", to_expression(ops[1]), ", ",
to_expression(ops[2]), ", ", to_expression(ops[3]), ", ",
to_expression(ops[4]), ", ", to_expression(ops[5]), ", ",
to_expression(ops[6]), ", ", to_expression(ops[7]), ");");
break;
case OpRayQueryProceedKHR:
emit_op(ops[0], ops[1], join("rayQueryProceedEXT(", to_expression(ops[2]), ")"), false);
break;
case OpRayQueryTerminateKHR:
statement("rayQueryTerminateEXT(", to_expression(ops[0]), ");");
break;
case OpRayQueryGenerateIntersectionKHR:
statement("rayQueryGenerateIntersectionEXT(", to_expression(ops[0]), ", ", to_expression(ops[1]), ");");
break;
case OpRayQueryConfirmIntersectionKHR:
statement("rayQueryConfirmIntersectionEXT(", to_expression(ops[0]), ");");
break;
#define GLSL_RAY_QUERY_GET_OP(op) \
case OpRayQueryGet##op##KHR: \
emit_op(ops[0], ops[1], join("rayQueryGet" #op "EXT(", to_expression(ops[2]), ")"), false); \
break
#define GLSL_RAY_QUERY_GET_OP2(op) \
case OpRayQueryGet##op##KHR: \
emit_op(ops[0], ops[1], join("rayQueryGet" #op "EXT(", to_expression(ops[2]), ", ", "bool(", to_expression(ops[3]), "))"), false); \
break
GLSL_RAY_QUERY_GET_OP(RayTMin);
GLSL_RAY_QUERY_GET_OP(RayFlags);
GLSL_RAY_QUERY_GET_OP(WorldRayOrigin);
GLSL_RAY_QUERY_GET_OP(WorldRayDirection);
GLSL_RAY_QUERY_GET_OP(IntersectionCandidateAABBOpaque);
GLSL_RAY_QUERY_GET_OP2(IntersectionType);
GLSL_RAY_QUERY_GET_OP2(IntersectionT);
GLSL_RAY_QUERY_GET_OP2(IntersectionInstanceCustomIndex);
GLSL_RAY_QUERY_GET_OP2(IntersectionInstanceId);
GLSL_RAY_QUERY_GET_OP2(IntersectionInstanceShaderBindingTableRecordOffset);
GLSL_RAY_QUERY_GET_OP2(IntersectionGeometryIndex);
GLSL_RAY_QUERY_GET_OP2(IntersectionPrimitiveIndex);
GLSL_RAY_QUERY_GET_OP2(IntersectionBarycentrics);
GLSL_RAY_QUERY_GET_OP2(IntersectionFrontFace);
GLSL_RAY_QUERY_GET_OP2(IntersectionObjectRayDirection);
GLSL_RAY_QUERY_GET_OP2(IntersectionObjectRayOrigin);
GLSL_RAY_QUERY_GET_OP2(IntersectionObjectToWorld);
GLSL_RAY_QUERY_GET_OP2(IntersectionWorldToObject);
#undef GLSL_RAY_QUERY_GET_OP
#undef GLSL_RAY_QUERY_GET_OP2
case OpConvertUToAccelerationStructureKHR: case OpConvertUToAccelerationStructureKHR:
require_extension_internal("GL_EXT_ray_tracing");
GLSL_UFOP(accelerationStructureEXT); GLSL_UFOP(accelerationStructureEXT);
break; break;
@ -13346,6 +13415,9 @@ string CompilerGLSL::type_to_glsl(const SPIRType &type, uint32_t id)
case SPIRType::AccelerationStructure: case SPIRType::AccelerationStructure:
return ray_tracing_is_khr ? "accelerationStructureEXT" : "accelerationStructureNV"; return ray_tracing_is_khr ? "accelerationStructureEXT" : "accelerationStructureNV";
case SPIRType::RayQuery:
return "rayQueryEXT";
case SPIRType::Void: case SPIRType::Void:
return "void"; return "void";