mirror of
https://github.com/w23/xash3d-fwgs
synced 2024-12-15 05:29:51 +01:00
Merge pull request #403 from w23/primary-ray-compute
Convert primary ray pass to compute shader Makes it work under open source mesa amdgpu driver (although it's ~30% slower than the old binary driver)
This commit is contained in:
commit
ab59393909
@ -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):
|
||||
|
@ -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);
|
||||
|
||||
|
58
ref_vk/shaders/ray_primary.comp
Normal file
58
ref_vk/shaders/ray_primary.comp
Normal file
@ -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);
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#version 460 core
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_ray_tracing: require
|
||||
|
||||
#include "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
|
||||
|
61
ref_vk/shaders/ray_primary_hit.glsl
Normal file
61
ref_vk/shaders/ray_primary_hit.glsl
Normal file
@ -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
|
@ -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" }, },
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user