Skip to content

Commit

Permalink
rt: compute the primary ray
Browse files Browse the repository at this point in the history
  • Loading branch information
w23 committed Jan 22, 2023
1 parent 9f37352 commit 28f40d5
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 29 deletions.
18 changes: 9 additions & 9 deletions ref_vk/TODO.md
Original file line number Diff line number Diff line change
@@ -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):
Expand Down
3 changes: 2 additions & 1 deletion ref_vk/shaders/ray_common_alphatest.rahit
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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);

Expand Down
58 changes: 58 additions & 0 deletions ref_vk/shaders/ray_primary.comp
Original file line number Diff line number Diff line change
@@ -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);
}
6 changes: 2 additions & 4 deletions ref_vk/shaders/ray_primary.rchit
Original file line number Diff line number Diff line change
@@ -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];
Expand All @@ -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);

Expand Down
1 change: 1 addition & 0 deletions ref_vk/shaders/ray_primary.rgen
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#version 460 core
#extension GL_GOOGLE_include_directive : require
#extension GL_EXT_ray_tracing: require

#include "ray_primary_common.glsl"

Expand Down
5 changes: 4 additions & 1 deletion ref_vk/shaders/ray_primary_common.glsl
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -13,3 +14,5 @@ struct RayPayloadPrimary {
};

#define PAYLOAD_LOCATION_PRIMARY 0

#endif //ifndef RAY_PRIMARY_COMMON_GLSL_INCLUDED
61 changes: 61 additions & 0 deletions ref_vk/shaders/ray_primary_hit.glsl
Original file line number Diff line number Diff line change
@@ -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
7 changes: 5 additions & 2 deletions ref_vk/shaders/rt.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{

"primary_ray": {
/*
"rgen": "ray_primary",
"miss": [
"ray_primary"
Expand All @@ -9,6 +9,8 @@
{"closest": "ray_primary"},
{"closest": "ray_primary", "any": "ray_common_alphatest"}
]
*/
"comp": "ray_primary"
},
// "light_direct": {
// "template": true,
Expand All @@ -35,5 +37,6 @@
},
"denoiser": {
"comp": "denoiser"
}
},
//"RESOURCES": { "position_t_prev": { "previous_frame": "position_t" }, },
}
37 changes: 28 additions & 9 deletions ref_vk/shaders/rt_geometry.glsl
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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] = {
Expand All @@ -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,
Expand All @@ -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
6 changes: 3 additions & 3 deletions ref_vk/vk_rtx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand All @@ -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);
}

Expand Down

0 comments on commit 28f40d5

Please sign in to comment.