From 28f40d5ca08d0456f3275ed51d163daf948ddb8d Mon Sep 17 00:00:00 2001 From: Ivan 'provod' Avdeev Date: Sun, 22 Jan 2023 15:00:01 -0800 Subject: [PATCH] rt: compute the primary ray --- ref_vk/TODO.md | 18 +++---- ref_vk/shaders/ray_common_alphatest.rahit | 3 +- ref_vk/shaders/ray_primary.comp | 58 +++++++++++++++++++++ ref_vk/shaders/ray_primary.rchit | 6 +-- ref_vk/shaders/ray_primary.rgen | 1 + ref_vk/shaders/ray_primary_common.glsl | 5 +- ref_vk/shaders/ray_primary_hit.glsl | 61 +++++++++++++++++++++++ ref_vk/shaders/rt.json | 7 ++- ref_vk/shaders/rt_geometry.glsl | 37 ++++++++++---- ref_vk/vk_rtx.c | 6 +-- 10 files changed, 173 insertions(+), 29 deletions(-) create mode 100644 ref_vk/shaders/ray_primary.comp create mode 100644 ref_vk/shaders/ray_primary_hit.glsl diff --git a/ref_vk/TODO.md b/ref_vk/TODO.md index ce3fc37b..15a39078 100644 --- a/ref_vk/TODO.md +++ b/ref_vk/TODO.md @@ -1,19 +1,19 @@ # Real next >=E222 - - [x] refcount meatpipe created images - - [ ] previous frame resources reference - - [ ] what if new meatpipe has different image format for a creatable image? - - [ ] rake yuri primary ray - - [ ] resource management refactoring: - - [ ] register existing resources (tlas, buffers, temp images, ...) in their producers - - [ ] resource automatic resolution: prducing, barriers, etc - - [ ] resource destruction - - [ ] ? resource object: name, metadata(type, etc.), producer, status (ready, barriers, etc) +- [x] refcount meatpipe created images +- [x] rake yuri primary ray +- [ ] previous frame resources reference +- [ ] what if new meatpipe has different image format for a creatable image? # Programmable render - [ ] implicit dependency tracking. pass defines: - [ ] imports: list of things it needs - [ ] exports: list of things it produces. those get created and registered with this pass as a producer +- [ ] resource management refactoring: + - [ ] register existing resources (tlas, buffers, temp images, ...) in their producers + - [ ] resource automatic resolution: prducing, barriers, etc + - [ ] resource destruction +- [ ] ? resource object: name, metadata(type, etc.), producer, status (ready, barriers, etc) # Parallel frames sync - [ ] light_grid_buffer (+ small lights_buffer): diff --git a/ref_vk/shaders/ray_common_alphatest.rahit b/ref_vk/shaders/ray_common_alphatest.rahit index a864c5e1..c6f92d18 100644 --- a/ref_vk/shaders/ray_common_alphatest.rahit +++ b/ref_vk/shaders/ray_common_alphatest.rahit @@ -1,6 +1,7 @@ #version 460 core #extension GL_EXT_nonuniform_qualifier : enable #extension GL_GOOGLE_include_directive : require +#extension GL_EXT_ray_tracing: require #include "ray_primary_common.glsl" #include "ray_kusochki.glsl" @@ -19,7 +20,7 @@ hitAttributeEXT vec2 bary; const float alpha_mask_threshold = .1f; void main() { - const Geometry geom = readHitGeometry(); + const Geometry geom = readHitGeometry(bary, ubo.ubo.ray_cone_width); const uint tex_index = getKusok(geom.kusok_index).tex_base_color; const vec4 texture_color = texture(textures[nonuniformEXT(tex_index)], geom.uv); diff --git a/ref_vk/shaders/ray_primary.comp b/ref_vk/shaders/ray_primary.comp new file mode 100644 index 00000000..c747cf3c --- /dev/null +++ b/ref_vk/shaders/ray_primary.comp @@ -0,0 +1,58 @@ +#version 460 core +#extension GL_GOOGLE_include_directive : require +#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_ray_query: require + +#define RAY_QUERY +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +#include "ray_primary_common.glsl" +#include "ray_primary_hit.glsl" + +#define X(index, name, format) layout(set=0,binding=index,format) uniform writeonly image2D out_##name; +RAY_PRIMARY_OUTPUTS(X) +#undef X + +layout(set = 0, binding = 1) uniform accelerationStructureEXT tlas; + +void main() { + const ivec2 pix = ivec2(gl_GlobalInvocationID); + const ivec2 res = ivec2(imageSize(out_position_t)); + if (any(greaterThanEqual(pix, res))) { + return; + } + const vec2 uv = (gl_GlobalInvocationID.xy + .5) / res * 2. - 1.; + + // FIXME start on a near plane + const vec3 origin = (ubo.ubo.inv_view * vec4(0, 0, 0, 1)).xyz; + const vec4 target = ubo.ubo.inv_proj * vec4(uv.x, uv.y, 1, 1); + const vec3 direction = normalize((ubo.ubo.inv_view * vec4(target.xyz, 0)).xyz); + + RayPayloadPrimary payload; + payload.hit_t = vec4(0.); + payload.base_color_a = vec4(0.); + payload.normals_gs = vec4(0.); + payload.material_rmxx = vec4(0.); + payload.emissive = vec4(0.); + + rayQueryEXT rq; + const uint flags = 0 + | gl_RayFlagsCullFrontFacingTrianglesEXT + //| gl_RayFlagsOpaqueEXT + //| gl_RayFlagsTerminateOnFirstHitEXT + //| gl_RayFlagsSkipClosestHitShaderEXT + ; + const float L = 10000.; // TODO Why 10k? + rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_OPAQUE, origin, 0., direction, L); + // TODO alpha test + while (rayQueryProceedEXT(rq)) { } + if (rayQueryGetIntersectionTypeEXT(rq, true) == gl_RayQueryCommittedIntersectionTriangleEXT) { + primaryRayHit(rq, payload); + } + + imageStore(out_position_t, pix, payload.hit_t); + imageStore(out_base_color_a, pix, payload.base_color_a); + imageStore(out_normals_gs, pix, payload.normals_gs); + imageStore(out_material_rmxx, pix, payload.material_rmxx); + imageStore(out_emissive, pix, payload.emissive); +} diff --git a/ref_vk/shaders/ray_primary.rchit b/ref_vk/shaders/ray_primary.rchit index c2073d47..3d0a02a5 100644 --- a/ref_vk/shaders/ray_primary.rchit +++ b/ref_vk/shaders/ray_primary.rchit @@ -1,13 +1,11 @@ #version 460 core #extension GL_GOOGLE_include_directive : require #extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_ray_tracing: require #include "utils.glsl" - #include "ray_primary_common.glsl" - #include "ray_kusochki.glsl" - #include "color_spaces.glsl" layout(set = 0, binding = 6) uniform sampler2D textures[MAX_TEXTURES]; @@ -24,7 +22,7 @@ vec4 sampleTexture(uint tex_index, vec2 uv, vec4 uv_lods) { } void main() { - Geometry geom = readHitGeometry(); + Geometry geom = readHitGeometry(bary, ubo.ubo.ray_cone_width); payload.hit_t = vec4(geom.pos, gl_HitTEXT); diff --git a/ref_vk/shaders/ray_primary.rgen b/ref_vk/shaders/ray_primary.rgen index 117268e1..ba7fdbcf 100644 --- a/ref_vk/shaders/ray_primary.rgen +++ b/ref_vk/shaders/ray_primary.rgen @@ -1,5 +1,6 @@ #version 460 core #extension GL_GOOGLE_include_directive : require +#extension GL_EXT_ray_tracing: require #include "ray_primary_common.glsl" diff --git a/ref_vk/shaders/ray_primary_common.glsl b/ref_vk/shaders/ray_primary_common.glsl index fd593ee0..9662d825 100644 --- a/ref_vk/shaders/ray_primary_common.glsl +++ b/ref_vk/shaders/ray_primary_common.glsl @@ -1,4 +1,5 @@ -#extension GL_EXT_ray_tracing: require +#ifndef RAY_PRIMARY_COMMON_GLSL_INCLUDED +#define RAY_PRIMARY_COMMON_GLSL_INCLUDED #define GLSL #include "ray_interop.h" @@ -13,3 +14,5 @@ struct RayPayloadPrimary { }; #define PAYLOAD_LOCATION_PRIMARY 0 + +#endif //ifndef RAY_PRIMARY_COMMON_GLSL_INCLUDED diff --git a/ref_vk/shaders/ray_primary_hit.glsl b/ref_vk/shaders/ray_primary_hit.glsl new file mode 100644 index 00000000..fd707a84 --- /dev/null +++ b/ref_vk/shaders/ray_primary_hit.glsl @@ -0,0 +1,61 @@ +#ifndef RAY_PRIMARY_HIT_GLSL_INCLUDED +#define RAY_PRIMARY_HIT_GLSL_INCLUDED +#extension GL_EXT_nonuniform_qualifier : enable + +#include "utils.glsl" +#include "ray_primary_common.glsl" +#include "ray_kusochki.glsl" +#include "rt_geometry.glsl" +#include "color_spaces.glsl" + +layout(set = 0, binding = 6) uniform sampler2D textures[MAX_TEXTURES]; +layout(set = 0, binding = 2) uniform UBO { UniformBuffer ubo; } ubo; +layout(set = 0, binding = 7) uniform samplerCube skybox; + +vec4 sampleTexture(uint tex_index, vec2 uv, vec4 uv_lods) { + return textureGrad(textures[nonuniformEXT(tex_index)], uv, uv_lods.xy, uv_lods.zw); +} + +void primaryRayHit(rayQueryEXT rq, inout RayPayloadPrimary payload) { + Geometry geom = readHitGeometry(rq, ubo.ubo.ray_cone_width, rayQueryGetIntersectionBarycentricsEXT(rq, true)); + const float hitT = rayQueryGetIntersectionTEXT(rq, true); //gl_HitTEXT; + const vec3 rayDirection = rayQueryGetWorldRayDirectionEXT(rq); //gl_WorldRayDirectionEXT + payload.hit_t = vec4(geom.pos, hitT); + + const Kusok kusok = getKusok(geom.kusok_index); + const uint tex_base_color = kusok.tex_base_color; + + if ((tex_base_color & KUSOK_MATERIAL_FLAG_SKYBOX) != 0) { + payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, rayDirection).rgb); + return; + } else { + payload.base_color_a = sampleTexture(tex_base_color, geom.uv, geom.uv_lods) * kusok.color; + payload.material_rmxx.r = (kusok.tex_roughness > 0) ? sampleTexture(kusok.tex_roughness, geom.uv, geom.uv_lods).r : kusok.roughness; + payload.material_rmxx.g = (kusok.tex_metalness > 0) ? sampleTexture(kusok.tex_metalness, geom.uv, geom.uv_lods).r : kusok.metalness; + + const uint tex_normal = kusok.tex_normalmap; + vec3 T = geom.tangent; + if (tex_normal > 0 && dot(T,T) > .5) { + T = normalize(T - dot(T, geom.normal_shading) * geom.normal_shading); + const vec3 B = normalize(cross(geom.normal_shading, T)); + const mat3 TBN = mat3(T, B, geom.normal_shading); + const vec3 tnorm = sampleTexture(tex_normal, geom.uv, geom.uv_lods).xyz * 2. - 1.; // TODO is this sampling correct for normal data? + geom.normal_shading = normalize(TBN * tnorm); + } + } + + payload.normals_gs.xy = normalEncode(geom.normal_geometry); + payload.normals_gs.zw = normalEncode(geom.normal_shading); + +#if 1 + // Real correct emissive color + //payload.emissive.rgb = kusok.emissive; + payload.emissive.rgb = clamp(kusok.emissive / (1.0/3.0) / 25, 0, 1.5) * SRGBtoLINEAR(payload.base_color_a.rgb); +#else + // Fake texture color + if (any(greaterThan(kusok.emissive, vec3(0.)))) + payload.emissive.rgb = payload.base_color_a.rgb; +#endif +} + +#endif // ifndef RAY_PRIMARY_HIT_GLSL_INCLUDED diff --git a/ref_vk/shaders/rt.json b/ref_vk/shaders/rt.json index b8e10225..23652e30 100644 --- a/ref_vk/shaders/rt.json +++ b/ref_vk/shaders/rt.json @@ -1,6 +1,6 @@ { - "primary_ray": { + /* "rgen": "ray_primary", "miss": [ "ray_primary" @@ -9,6 +9,8 @@ {"closest": "ray_primary"}, {"closest": "ray_primary", "any": "ray_common_alphatest"} ] + */ + "comp": "ray_primary" }, // "light_direct": { // "template": true, @@ -35,5 +37,6 @@ }, "denoiser": { "comp": "denoiser" - } + }, + //"RESOURCES": { "position_t_prev": { "previous_frame": "position_t" }, }, } diff --git a/ref_vk/shaders/rt_geometry.glsl b/ref_vk/shaders/rt_geometry.glsl index f232035e..a84f3e12 100644 --- a/ref_vk/shaders/rt_geometry.glsl +++ b/ref_vk/shaders/rt_geometry.glsl @@ -1,3 +1,5 @@ +#ifndef RT_GEOMETRY_GLSL_INCLUDED +#define RT_GEOMETRY_GLSL_INCLUDED #include "utils.glsl" // Taken from Journal of Computer Graphics Techniques, Vol. 10, No. 1, 2021. @@ -51,22 +53,38 @@ struct Geometry { int kusok_index; }; -Geometry readHitGeometry() { +#ifdef RAY_QUERY +Geometry readHitGeometry(rayQueryEXT rq, float ray_cone_width, vec2 bary) { + const int instance_kusochki_offset = rayQueryGetIntersectionInstanceCustomIndexEXT(rq, true); + const int geometry_index = rayQueryGetIntersectionGeometryIndexEXT(rq, true); + const int primitive_index = rayQueryGetIntersectionPrimitiveIndexEXT(rq, true); + const mat4x3 objectToWorld = rayQueryGetIntersectionObjectToWorldEXT(rq, true); + const vec3 ray_direction = rayQueryGetWorldRayDirectionEXT(rq); + const float hit_t = rayQueryGetIntersectionTEXT(rq, true); +#else +Geometry readHitGeometry(vec2 bary, float ray_cone_width) { + const int instance_kusochki_offset = gl_InstanceCustomIndexEXT; + const int geometry_index = gl_GeometryIndexEXT; + const int primitive_index = gl_PrimitiveID; + const mat4x3 objectToWorld = gl_ObjectToWorldEXT; + const vec3 ray_direction = gl_WorldRayDirectionEXT; + const float hit_t = gl_HitTEXT; +#endif + Geometry geom; - const int instance_kusochki_offset = gl_InstanceCustomIndexEXT; - geom.kusok_index = instance_kusochki_offset + gl_GeometryIndexEXT; + geom.kusok_index = instance_kusochki_offset + geometry_index; const Kusok kusok = getKusok(geom.kusok_index); - const uint first_index_offset = kusok.index_offset + gl_PrimitiveID * 3; + const uint first_index_offset = kusok.index_offset + primitive_index * 3; const uint vi1 = uint(getIndex(first_index_offset+0)) + kusok.vertex_offset; const uint vi2 = uint(getIndex(first_index_offset+1)) + kusok.vertex_offset; const uint vi3 = uint(getIndex(first_index_offset+2)) + kusok.vertex_offset; const vec3 pos[3] = { - gl_ObjectToWorldEXT * vec4(getVertex(vi1).pos, 1.f), - gl_ObjectToWorldEXT * vec4(getVertex(vi2).pos, 1.f), - gl_ObjectToWorldEXT * vec4(getVertex(vi3).pos, 1.f), + objectToWorld * vec4(getVertex(vi1).pos, 1.f), + objectToWorld * vec4(getVertex(vi2).pos, 1.f), + objectToWorld * vec4(getVertex(vi3).pos, 1.f), }; const vec2 uvs[3] = { @@ -83,7 +101,7 @@ Geometry readHitGeometry() { geom.normal_geometry = normalize(cross(pos[2]-pos[0], pos[1]-pos[0])); // NOTE: only support rotations, for arbitrary transform would need to do transpose(inverse(mat3(gl_ObjectToWorldEXT))) - const mat3 normalTransform = mat3(gl_ObjectToWorldEXT); + const mat3 normalTransform = mat3(objectToWorld); // mat3(gl_ObjectToWorldEXT); geom.normal_shading = normalize(normalTransform * baryMix( getVertex(vi1).normal, getVertex(vi2).normal, @@ -95,7 +113,8 @@ Geometry readHitGeometry() { getVertex(vi3).tangent, bary)); - geom.uv_lods = computeAnisotropicEllipseAxes(geom.pos, geom.normal_geometry, gl_WorldRayDirectionEXT, ubo.ubo.ray_cone_width * gl_HitTEXT, pos, uvs, geom.uv); + geom.uv_lods = computeAnisotropicEllipseAxes(geom.pos, geom.normal_geometry, ray_direction, ray_cone_width * hit_t, pos, uvs, geom.uv); return geom; } +#endif // RT_GEOMETRY_GLSL_INCLUDED diff --git a/ref_vk/vk_rtx.c b/ref_vk/vk_rtx.c index 85b42019..7f1bba11 100644 --- a/ref_vk/vk_rtx.c +++ b/ref_vk/vk_rtx.c @@ -224,7 +224,7 @@ static void performTracing(VkCommandBuffer cmdbuf, const perform_tracing_args_t* vkCmdPipelineBarrier(cmdbuf, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR | VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR | VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, ARRAYSIZE(bmb), bmb, 0, NULL); } @@ -253,7 +253,7 @@ static void performTracing(VkCommandBuffer cmdbuf, const perform_tracing_args_t* } }; vkCmdPipelineBarrier(cmdbuf, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, - VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, ARRAYSIZE(bmb), bmb, 0, NULL); } @@ -270,7 +270,7 @@ static void performTracing(VkCommandBuffer cmdbuf, const perform_tracing_args_t* }}; vkCmdPipelineBarrier(cmdbuf, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, ARRAYSIZE(bmb), bmb, 0, NULL); }