mirror of
https://github.com/w23/xash3d-fwgs
synced 2024-12-16 06:00:33 +01:00
rt: draft direct light compute shader
it's bad: direct light: 1.8ms, 183(184)v, 59(128)s, LDS=0, 2/16o (-56 vgpr => +1 wavefront??) also, thread group size = 16, 8, 1, wave64 while ray tracing pipeline = 8, 4, 1, wave32
This commit is contained in:
parent
b9760aaaea
commit
af24afbcc3
@ -72,7 +72,8 @@ void main() {
|
||||
//imageStore(dest, pix, vec4((base_color.rgb), 0.)); return;
|
||||
//imageStore(dest, pix, vec4(fract(imageLoad(src_position_t, pix).rgb / 10.), 0.)); return;
|
||||
//imageStore(dest, pix, vec4((imageLoad(src_diffuse_gi, pix).rgb), 0.)); return;
|
||||
imageStore(dest, pix, vec4(imageLoad(src_normals, pix)*.5 + .5f)); return;
|
||||
//imageStore(dest, pix, vec4((imageLoad(src_diffuse_gi, pix).rgb * base_color.rgb), 0.)); return;
|
||||
//imageStore(dest, pix, vec4(imageLoad(src_normals, pix)*.5 + .5f)); return;
|
||||
//imageStore(dest, pix, vec4(aces_tonemap(imageLoad(src_diffuse_gi, pix).rgb), 0.)); return;
|
||||
//imageStore(dest, pix, vec4(aces_tonemap(imageLoad(src_specular, pix).rgb), 0.)); return;
|
||||
|
||||
@ -85,10 +86,13 @@ void main() {
|
||||
/* imageStore(dest, pix, vec4(rand3_f01(uvec3(mi,mi+1,mi+2)), 0.)); */
|
||||
/* return; */
|
||||
|
||||
const int KERNEL_SIZE = 8;
|
||||
#if 1
|
||||
vec3 colour = imageLoad(src_diffuse_gi, pix).rgb * base_color.rgb;
|
||||
#else
|
||||
float total_scale = 0.;
|
||||
float specular_total_scale = 0.;
|
||||
vec3 colour = vec3(0.);
|
||||
const int KERNEL_SIZE = 8;
|
||||
float specular_total_scale = 0.;
|
||||
vec3 speculour = vec3(0.);
|
||||
for (int x = -KERNEL_SIZE; x <= KERNEL_SIZE; ++x)
|
||||
for (int y = -KERNEL_SIZE; y <= KERNEL_SIZE; ++y) {
|
||||
@ -137,6 +141,7 @@ void main() {
|
||||
|
||||
//colour += imageLoad(src_specular, pix).rgb;
|
||||
colour += imageLoad(src_additive, pix).rgb;
|
||||
#endif
|
||||
|
||||
// HACK: exposure
|
||||
// TODO: should be dynamic based on previous frames brightness
|
||||
|
132
ref_vk/shaders/light.glsl
Normal file
132
ref_vk/shaders/light.glsl
Normal file
@ -0,0 +1,132 @@
|
||||
layout (constant_id = 4) const float LIGHT_GRID_CELL_SIZE = 256.;
|
||||
layout (constant_id = 5) const uint MAX_LIGHT_CLUSTERS = 32768;
|
||||
layout (constant_id = 6) const uint MAX_TEXTURES = 4096;
|
||||
layout (set = 0, binding = BINDING_LIGHTS) uniform UBOLights { Lights lights; };
|
||||
layout (set = 0, binding = BINDING_LIGHT_CLUSTERS, align = 1) readonly buffer UBOLightClusters {
|
||||
ivec3 grid_min, grid_size;
|
||||
//uint8_t clusters_data[MAX_LIGHT_CLUSTERS * LIGHT_CLUSTER_SIZE + HACK_OFFSET];
|
||||
LightCluster clusters[MAX_LIGHT_CLUSTERS];
|
||||
} light_grid;
|
||||
|
||||
const float color_culling_threshold = 0;//600./color_factor;
|
||||
const float shadow_offset_fudge = .1;
|
||||
|
||||
#include "brdf.h"
|
||||
#include "light_common.glsl"
|
||||
#include "light_polygon.glsl"
|
||||
|
||||
void computePointLights(vec3 P, vec3 N, uint cluster_index, vec3 throughput, vec3 view_dir, MaterialProperties material, out vec3 diffuse, out vec3 specular) {
|
||||
diffuse = specular = vec3(0.);
|
||||
const uint num_point_lights = uint(light_grid.clusters[cluster_index].num_point_lights);
|
||||
for (uint j = 0; j < num_point_lights; ++j) {
|
||||
const uint i = uint(light_grid.clusters[cluster_index].point_lights[j]);
|
||||
|
||||
vec3 color = lights.point_lights[i].color_stopdot.rgb * throughput;
|
||||
if (dot(color,color) < color_culling_threshold)
|
||||
continue;
|
||||
|
||||
const vec4 origin_r = lights.point_lights[i].origin_r;
|
||||
const float stopdot = lights.point_lights[i].color_stopdot.a;
|
||||
const vec3 dir = lights.point_lights[i].dir_stopdot2.xyz;
|
||||
const float stopdot2 = lights.point_lights[i].dir_stopdot2.a;
|
||||
const bool not_environment = (lights.point_lights[i].environment == 0);
|
||||
|
||||
const vec3 light_dir = not_environment ? (origin_r.xyz - P) : -dir; // TODO need to randomize sampling direction for environment soft shadow
|
||||
const float radius = origin_r.w;
|
||||
|
||||
const vec3 light_dir_norm = normalize(light_dir);
|
||||
const float light_dot = dot(light_dir_norm, N);
|
||||
if (light_dot < 1e-5)
|
||||
continue;
|
||||
|
||||
const float spot_dot = -dot(light_dir_norm, dir);
|
||||
if (spot_dot < stopdot2)
|
||||
continue;
|
||||
|
||||
float spot_attenuation = 1.f;
|
||||
if (spot_dot < stopdot)
|
||||
spot_attenuation = (spot_dot - stopdot2) / (stopdot - stopdot2);
|
||||
|
||||
//float fdist = 1.f;
|
||||
float light_dist = 1e5; // TODO this is supposedly not the right way to do shadows for environment lights. qrad checks for hitting SURF_SKY, and maybe we should too?
|
||||
const float d2 = dot(light_dir, light_dir);
|
||||
const float r2 = origin_r.w * origin_r.w;
|
||||
if (not_environment) {
|
||||
if (radius < 1e-3)
|
||||
continue;
|
||||
|
||||
const float dist = length(light_dir);
|
||||
if (radius > dist)
|
||||
continue;
|
||||
#if 1
|
||||
//light_dist = sqrt(d2);
|
||||
light_dist = dist - radius;
|
||||
//fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
||||
#else
|
||||
light_dist = dist;
|
||||
//const float fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
||||
//const float fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
||||
//fdist = (light_dist > 1.) ? 1.f / d2 : 1.f; // qrad workaround
|
||||
#endif
|
||||
|
||||
//const float pdf = 1.f / (fdist * light_dot * spot_attenuation);
|
||||
//const float pdf = TWO_PI / asin(radius / dist);
|
||||
const float pdf = 1. / ((1. - sqrt(d2 - r2) / dist) * spot_attenuation);
|
||||
color /= pdf;
|
||||
}
|
||||
|
||||
// if (dot(color,color) < color_culling_threshold)
|
||||
// continue;
|
||||
|
||||
vec3 ldiffuse, lspecular;
|
||||
evalSplitBRDF(N, light_dir_norm, view_dir, material, ldiffuse, lspecular);
|
||||
ldiffuse *= color;
|
||||
lspecular *= color;
|
||||
|
||||
vec3 combined = ldiffuse + lspecular;
|
||||
|
||||
if (dot(combined,combined) < color_culling_threshold)
|
||||
continue;
|
||||
|
||||
if (not_environment) {
|
||||
if (shadowed(P, light_dir_norm, light_dist + shadow_offset_fudge))
|
||||
continue;
|
||||
} else {
|
||||
// for environment light check that we've hit SURF_SKY
|
||||
if (shadowedSky(P, light_dir_norm, light_dist + shadow_offset_fudge))
|
||||
continue;
|
||||
}
|
||||
|
||||
diffuse += ldiffuse;
|
||||
specular += lspecular;
|
||||
} // for all lights
|
||||
}
|
||||
|
||||
void computeLighting(vec3 P, vec3 N, vec3 throughput, vec3 view_dir, MaterialProperties material, out vec3 diffuse, out vec3 specular) {
|
||||
diffuse = specular = vec3(0.);
|
||||
const ivec3 light_cell = ivec3(floor(P / LIGHT_GRID_CELL_SIZE)) - light_grid.grid_min;
|
||||
const uint cluster_index = uint(dot(light_cell, ivec3(1, light_grid.grid_size.x, light_grid.grid_size.x * light_grid.grid_size.y)));
|
||||
|
||||
if (any(greaterThanEqual(light_cell, light_grid.grid_size)) || cluster_index >= MAX_LIGHT_CLUSTERS)
|
||||
return; // throughput * vec3(1., 0., 0.);
|
||||
|
||||
// const uint cluster_offset = cluster_index * LIGHT_CLUSTER_SIZE + HACK_OFFSET;
|
||||
// const int num_dlights = int(light_grid.clusters_data[cluster_offset + LIGHT_CLUSTER_NUM_DLIGHTS_OFFSET]);
|
||||
// const int num_emissive_surfaces = int(light_grid.clusters_data[cluster_offset + LIGHT_CLUSTER_NUM_EMISSIVE_SURFACES_OFFSET]);
|
||||
// const uint emissive_surfaces_offset = cluster_offset + LIGHT_CLUSTER_EMISSIVE_SURFACES_DATA_OFFSET;
|
||||
//C = vec3(float(num_emissive_surfaces));
|
||||
|
||||
//C = vec3(float(int(light_grid.clusters[cluster_index].num_emissive_surfaces)));
|
||||
//C += .3 * fract(vec3(light_cell) / 4.);
|
||||
|
||||
#if 1
|
||||
sampleEmissiveSurfaces(P, N, throughput, view_dir, material, cluster_index, diffuse, specular);
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
vec3 ldiffuse = vec3(0.), lspecular = vec3(0.);
|
||||
computePointLights(P, N, cluster_index, throughput, view_dir, material, ldiffuse, lspecular);
|
||||
diffuse += ldiffuse;
|
||||
specular += lspecular;
|
||||
#endif
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
bool shadowed(vec3 pos, vec3 dir, float dist) {
|
||||
#if 0
|
||||
payload_shadow.hit_type = SHADOW_HIT;
|
||||
const uint flags = 0
|
||||
//| gl_RayFlagsCullFrontFacingTrianglesEXT
|
||||
@ -12,10 +13,14 @@ bool shadowed(vec3 pos, vec3 dir, float dist) {
|
||||
SHADER_OFFSET_HIT_SHADOW_BASE, SBT_RECORD_SIZE, SHADER_OFFSET_MISS_SHADOW,
|
||||
pos, 0., dir, dist - shadow_offset_fudge, PAYLOAD_LOCATION_SHADOW);
|
||||
return payload_shadow.hit_type == SHADOW_HIT;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO join with just shadowed()
|
||||
bool shadowedSky(vec3 pos, vec3 dir, float dist) {
|
||||
#if 0
|
||||
payload_shadow.hit_type = SHADOW_HIT;
|
||||
const uint flags = 0
|
||||
//| gl_RayFlagsCullFrontFacingTrianglesEXT
|
||||
@ -29,6 +34,9 @@ bool shadowedSky(vec3 pos, vec3 dir, float dist) {
|
||||
SHADER_OFFSET_HIT_SHADOW_BASE, SBT_RECORD_SIZE, SHADER_OFFSET_MISS_SHADOW,
|
||||
pos, 0., dir, dist - shadow_offset_fudge, PAYLOAD_LOCATION_SHADOW);
|
||||
return payload_shadow.hit_type != SHADOW_SKY;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// This is an entry point for evaluation of all other BRDFs based on selected configuration (for direct light)
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include "peters2021-sampling/polygon_clipping.glsl"
|
||||
#include "peters2021-sampling/polygon_sampling.glsl"
|
||||
|
||||
#include "noise.glsl"
|
||||
|
||||
struct SampleContext {
|
||||
mat4x3 world_to_shading;
|
||||
};
|
||||
@ -22,8 +24,10 @@ void sampleEmissiveSurface(vec3 P, vec3 N, vec3 throughput, vec3 view_dir, Mater
|
||||
|
||||
const EmissiveKusok ek = lights.kusochki[ekusok_index];
|
||||
const uint emissive_kusok_index = lights.kusochki[ekusok_index].kusok_index;
|
||||
if (emissive_kusok_index == uint(payload_opaque.kusok_index))
|
||||
return;
|
||||
|
||||
// FIXME
|
||||
// if (emissive_kusok_index == uint(payload_opaque.kusok_index))
|
||||
// return;
|
||||
|
||||
const Kusok kusok = kusochki[emissive_kusok_index];
|
||||
|
||||
@ -167,10 +171,12 @@ void sampleEmissiveSurfaces(vec3 P, vec3 N, vec3 throughput, vec3 view_dir, Mate
|
||||
#endif
|
||||
const uint index_into_emissive_kusochki = uint(light_grid.clusters[cluster_index].emissive_surfaces[i]);
|
||||
|
||||
#if 0
|
||||
if (push_constants.debug_light_index_begin < push_constants.debug_light_index_end) {
|
||||
if (index_into_emissive_kusochki < push_constants.debug_light_index_begin || index_into_emissive_kusochki >= push_constants.debug_light_index_end)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
vec3 ldiffuse, lspecular;
|
||||
sampleEmissiveSurface(P, N, throughput, view_dir, material, ctx, index_into_emissive_kusochki, ldiffuse, lspecular);
|
||||
|
@ -1,3 +1,5 @@
|
||||
#ifndef NOISE_GLSL_INCLUDED
|
||||
#define NOISE_GLSL_INCLUDED
|
||||
// Copypasted from Mark Jarzynski and Marc Olano, Hash Functions for GPU Rendering, Journal of Computer Graphics Techniques (JCGT), vol. 9, no. 3, 21-38, 2020
|
||||
// http://www.jcgt.org/published/0009/03/02/
|
||||
// https://www.shadertoy.com/view/XlGcRh
|
||||
@ -119,19 +121,19 @@ uvec3 pcg3d16(uvec3 v)
|
||||
uvec4 pcg4d(uvec4 v)
|
||||
{
|
||||
v = v * 1664525u + 1013904223u;
|
||||
|
||||
|
||||
v.x += v.y*v.w;
|
||||
v.y += v.z*v.x;
|
||||
v.z += v.x*v.y;
|
||||
v.w += v.y*v.z;
|
||||
|
||||
|
||||
v ^= v >> 16u;
|
||||
|
||||
|
||||
v.x += v.y*v.w;
|
||||
v.y += v.z*v.x;
|
||||
v.z += v.x*v.y;
|
||||
v.w += v.y*v.z;
|
||||
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@ -154,4 +156,5 @@ float rand01() {
|
||||
vec3 rand3_f01(uvec3 seed) {
|
||||
uvec3 v = pcg3d(seed);
|
||||
return vec3(uintToFloat01(v.x), uintToFloat01(v.y), uintToFloat01(v.z));
|
||||
}
|
||||
}
|
||||
#endif // NOISE_GLSL_INCLUDED
|
||||
|
66
ref_vk/shaders/ray_light_direct.comp
Normal file
66
ref_vk/shaders/ray_light_direct.comp
Normal file
@ -0,0 +1,66 @@
|
||||
#version 460 core
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
//#extension GL_EXT_ray_query: require
|
||||
#extension GL_EXT_control_flow_attributes : require
|
||||
|
||||
layout(local_size_x = 16, local_size_y = 8, local_size_z = 1) in;
|
||||
|
||||
#include "ray_light_direct_iface.h"
|
||||
|
||||
#define GLSL
|
||||
#include "ray_interop.h"
|
||||
#undef GLSL
|
||||
|
||||
#define X(index, name, format) layout(set=0,binding=index,format) uniform readonly image2D name;
|
||||
RAY_LIGHT_DIRECT_INPUTS(X)
|
||||
#undef X
|
||||
#define X(index, name, format) layout(set=0,binding=index,format) uniform writeonly image2D out_image_##name;
|
||||
RAY_LIGHT_DIRECT_OUTPUTS(X)
|
||||
#undef X
|
||||
|
||||
//layout(set = 0, binding = 1) uniform accelerationStructureEXT tlas;
|
||||
layout(set = 0, binding = 2) uniform UBO { UniformBuffer ubo; };
|
||||
|
||||
#include "ray_kusochki.glsl"
|
||||
|
||||
#define BINDING_LIGHTS 7
|
||||
#define BINDING_LIGHT_CLUSTERS 8
|
||||
#include "light.glsl"
|
||||
|
||||
void readNormals(ivec2 uv, out vec3 geometry_normal, out vec3 shading_normal) {
|
||||
const vec4 n = imageLoad(normals_gs, uv);
|
||||
geometry_normal = vec3(n.xy, sqrt(1. - n.x*n.x - n.y*n.y));
|
||||
shading_normal = vec3(n.zw, sqrt(1. - n.z*n.z - n.w*n.w));
|
||||
}
|
||||
|
||||
void main() {
|
||||
//vec2 uv = (gl_LaunchIDEXT.xy + .5) / gl_LaunchSizeEXT.xy * 2. - 1.;
|
||||
const ivec2 res = ivec2(imageSize(position_t));
|
||||
const ivec2 pix = ivec2(gl_GlobalInvocationID);
|
||||
const vec2 uv = (pix + .5) / res * 2. - 1.;
|
||||
|
||||
rand01_state = /* FIXME push_constants.random_seed +*/ gl_GlobalInvocationID.x * 1833 + gl_GlobalInvocationID.y * 31337;
|
||||
|
||||
// FIXME incorrect for reflection/refraction
|
||||
vec4 target = ubo.inv_proj * vec4(uv.x, uv.y, 1, 1);
|
||||
vec3 direction = normalize((ubo.inv_view * vec4(target.xyz, 0)).xyz);
|
||||
|
||||
MaterialProperties material;
|
||||
material.baseColor = vec3(1.);
|
||||
material.emissive = vec3(0.f);
|
||||
material.metalness = 0.f; // TODO
|
||||
material.roughness = 1.f; // TODO
|
||||
|
||||
const vec3 pos = imageLoad(position_t, pix).xyz;
|
||||
|
||||
vec3 geometry_normal, shading_normal;
|
||||
readNormals(pix, geometry_normal, shading_normal);
|
||||
|
||||
const vec3 throughput = vec3(1.);
|
||||
vec3 diffuse = vec3(0.), specular = vec3(0.);
|
||||
computeLighting(pos, shading_normal, throughput, -direction, material, diffuse, specular);
|
||||
|
||||
imageStore(out_image_light_diffuse, pix, vec4(diffuse, 0.f));
|
||||
//imageStore(out_image_light_diffuse, pix, vec4(1.,0.,0.f, 0.f));
|
||||
imageStore(out_image_light_specular, pix, vec4(specular, 0.f));
|
||||
}
|
8
ref_vk/shaders/ray_light_direct_iface.h
Normal file
8
ref_vk/shaders/ray_light_direct_iface.h
Normal file
@ -0,0 +1,8 @@
|
||||
#define RAY_LIGHT_DIRECT_INPUTS(X) \
|
||||
X(10, position_t, rgba32f) \
|
||||
X(11, normals_gs, rgba16f) \
|
||||
|
||||
#define RAY_LIGHT_DIRECT_OUTPUTS(X) \
|
||||
X(13, light_diffuse, rgba16f) \
|
||||
X(14, light_specular, rgba16f) \
|
||||
|
@ -19,7 +19,8 @@ void main() {
|
||||
// FIXME start on a near plane
|
||||
vec3 origin = (ubo.inv_view * vec4(0, 0, 0, 1)).xyz;
|
||||
vec4 target = ubo.inv_proj * vec4(uv.x, uv.y, 1, 1);
|
||||
vec3 direction = (ubo.inv_view * vec4(normalize(target.xyz), 0)).xyz;
|
||||
//vec3 direction = (ubo.inv_view * vec4(normalize(target.xyz), 0)).xyz;
|
||||
vec3 direction = normalize((ubo.inv_view * vec4(target.xyz, 0)).xyz);
|
||||
|
||||
const uint flags = gl_RayFlagsCullFrontFacingTrianglesEXT;
|
||||
const uint sbt_offset = 0;
|
||||
|
177
ref_vk/vk_ray_light_direct.c
Normal file
177
ref_vk/vk_ray_light_direct.c
Normal file
@ -0,0 +1,177 @@
|
||||
#include "vk_ray_light_direct.h"
|
||||
#include "vk_ray_internal.h"
|
||||
|
||||
#include "vk_descriptor.h"
|
||||
#include "vk_pipeline.h"
|
||||
#include "vk_buffer.h"
|
||||
|
||||
#include "eiface.h" // ARRAYSIZE
|
||||
|
||||
enum {
|
||||
// TODO set 0
|
||||
//RtLDir_Desc_TLAS,
|
||||
RtLDir_Desc_UBO,
|
||||
RtLDir_Desc_Kusochki,
|
||||
RtLDir_Desc_Indices,
|
||||
RtLDir_Desc_Vertices,
|
||||
RtLDir_Desc_Textures,
|
||||
RtLDir_Desc_Lights,
|
||||
RtLDir_Desc_LightClusters,
|
||||
|
||||
// TODO set 1
|
||||
#define X(index, name, ...) RtLDir_Desc_##name,
|
||||
RAY_LIGHT_DIRECT_INPUTS(X)
|
||||
#undef X
|
||||
#define X(index, name, ...) RtLDir_Desc_##name,
|
||||
RAY_LIGHT_DIRECT_OUTPUTS(X)
|
||||
#undef X
|
||||
|
||||
RtLDir_Desc_COUNT
|
||||
};
|
||||
|
||||
static struct {
|
||||
struct {
|
||||
vk_descriptors_t riptors;
|
||||
VkDescriptorSetLayoutBinding bindings[RtLDir_Desc_COUNT];
|
||||
vk_descriptor_value_t values[RtLDir_Desc_COUNT];
|
||||
|
||||
// TODO: split into two sets, one common to all rt passes (tlas, kusochki, etc), another one this pass only
|
||||
VkDescriptorSet sets[1];
|
||||
} desc;
|
||||
|
||||
VkPipeline pipeline;
|
||||
} g_ray_light_direct;
|
||||
|
||||
static void initDescriptors( void ) {
|
||||
g_ray_light_direct.desc.riptors = (vk_descriptors_t) {
|
||||
.bindings = g_ray_light_direct.desc.bindings,
|
||||
.num_bindings = ARRAYSIZE(g_ray_light_direct.desc.bindings),
|
||||
.values = g_ray_light_direct.desc.values,
|
||||
.num_sets = ARRAYSIZE(g_ray_light_direct.desc.sets),
|
||||
.desc_sets = g_ray_light_direct.desc.sets,
|
||||
/* .push_constants = (VkPushConstantRange){ */
|
||||
/* .offset = 0, */
|
||||
/* .size = sizeof(vk_rtx_push_constants_t), */
|
||||
/* .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, */
|
||||
/* }, */
|
||||
};
|
||||
|
||||
#define INIT_BINDING(index, name, type, count) \
|
||||
g_ray_light_direct.desc.bindings[RtLDir_Desc_##name] = (VkDescriptorSetLayoutBinding){ \
|
||||
.binding = index, \
|
||||
.descriptorType = type, \
|
||||
.descriptorCount = count, \
|
||||
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, \
|
||||
}
|
||||
|
||||
//INIT_BINDING(1, TLAS, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1);
|
||||
INIT_BINDING(2, UBO, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
|
||||
INIT_BINDING(3, Kusochki, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1);
|
||||
INIT_BINDING(4, Indices, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1);
|
||||
INIT_BINDING(5, Vertices, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1);
|
||||
INIT_BINDING(6, Textures, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MAX_TEXTURES);
|
||||
INIT_BINDING(7, Lights, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
|
||||
//INIT_BINDING(7, Lights, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1);
|
||||
INIT_BINDING(8, LightClusters, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1);
|
||||
|
||||
//#define X(index, name, ...) INIT_BINDING(index, name, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1);
|
||||
#define X(index, name, ...) INIT_BINDING(index, name, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1);
|
||||
RAY_LIGHT_DIRECT_INPUTS(X)
|
||||
#undef X
|
||||
#define X(index, name, ...) INIT_BINDING(index, name, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1);
|
||||
RAY_LIGHT_DIRECT_OUTPUTS(X)
|
||||
#undef X
|
||||
#undef INIT_BINDING
|
||||
|
||||
VK_DescriptorsCreate(&g_ray_light_direct.desc.riptors);
|
||||
}
|
||||
|
||||
static void updateDescriptors( const xvk_ray_trace_light_direct_t* args ) {
|
||||
#define X(index, name, ...) \
|
||||
g_ray_light_direct.desc.values[RtLDir_Desc_##name].image = (VkDescriptorImageInfo){ \
|
||||
.sampler = VK_NULL_HANDLE, \
|
||||
.imageView = args->in.name, \
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL, \
|
||||
};
|
||||
RAY_LIGHT_DIRECT_INPUTS(X)
|
||||
#undef X
|
||||
|
||||
#define X(index, name, ...) \
|
||||
g_ray_light_direct.desc.values[RtLDir_Desc_##name].image = (VkDescriptorImageInfo){ \
|
||||
.sampler = VK_NULL_HANDLE, \
|
||||
.imageView = args->out.name, \
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL, \
|
||||
};
|
||||
RAY_LIGHT_DIRECT_OUTPUTS(X)
|
||||
|
||||
/* g_ray_light_direct.desc.values[RtLDir_Desc_TLAS].accel = (VkWriteDescriptorSetAccelerationStructureKHR){ */
|
||||
/* .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, */
|
||||
/* .accelerationStructureCount = 1, */
|
||||
/* .pAccelerationStructures = &args->in.tlas, */
|
||||
/* }; */
|
||||
|
||||
#define DESC_SET_BUFFER(index, buffer_) \
|
||||
g_ray_light_direct.desc.values[index].buffer = (VkDescriptorBufferInfo){ \
|
||||
.buffer = args->in.buffer_.buffer, \
|
||||
.offset = args->in.buffer_.offset, \
|
||||
.range = args->in.buffer_.size, \
|
||||
}
|
||||
|
||||
DESC_SET_BUFFER(RtLDir_Desc_UBO, ubo);
|
||||
DESC_SET_BUFFER(RtLDir_Desc_Kusochki, kusochki);
|
||||
DESC_SET_BUFFER(RtLDir_Desc_Indices, indices);
|
||||
DESC_SET_BUFFER(RtLDir_Desc_Vertices, vertices);
|
||||
DESC_SET_BUFFER(RtLDir_Desc_Lights, lights);
|
||||
DESC_SET_BUFFER(RtLDir_Desc_LightClusters, light_clusters);
|
||||
|
||||
#undef DESC_SET_BUFFER
|
||||
|
||||
g_ray_light_direct.desc.values[RtLDir_Desc_Textures].image_array = args->in.all_textures;
|
||||
|
||||
VK_DescriptorsWrite(&g_ray_light_direct.desc.riptors);
|
||||
}
|
||||
|
||||
static VkPipeline createPipeline( void ) {
|
||||
const vk_pipeline_compute_create_info_t pcci = {
|
||||
.layout = g_ray_light_direct.desc.riptors.pipeline_layout,
|
||||
.shader_filename = "ray_light_direct.comp.spv",
|
||||
.specialization_info = NULL,
|
||||
};
|
||||
|
||||
return VK_PipelineComputeCreate( &pcci );
|
||||
}
|
||||
|
||||
qboolean XVK_RayTraceLightDirectInit( void ) {
|
||||
initDescriptors();
|
||||
|
||||
g_ray_light_direct.pipeline = createPipeline();
|
||||
ASSERT(g_ray_light_direct.pipeline != VK_NULL_HANDLE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void XVK_RayTraceLightDirectDestroy( void ) {
|
||||
vkDestroyPipeline(vk_core.device, g_ray_light_direct.pipeline, NULL);
|
||||
VK_DescriptorsDestroy(&g_ray_light_direct.desc.riptors);
|
||||
}
|
||||
|
||||
void XVK_RayTraceLightDirectReloadPipeline( void ) {
|
||||
VkPipeline pipeline = createPipeline();
|
||||
if (pipeline == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
vkDestroyPipeline(vk_core.device, g_ray_light_direct.pipeline, NULL);
|
||||
g_ray_light_direct.pipeline = pipeline;
|
||||
}
|
||||
|
||||
void XVK_RayTraceLightDirect( VkCommandBuffer cmdbuf, const xvk_ray_trace_light_direct_t *args ) {
|
||||
const uint32_t WG_W = 16;
|
||||
const uint32_t WG_H = 8;
|
||||
|
||||
updateDescriptors( args );
|
||||
|
||||
vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_COMPUTE, g_ray_light_direct.pipeline);
|
||||
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_COMPUTE, g_ray_light_direct.desc.riptors.pipeline_layout, 0, 1, g_ray_light_direct.desc.riptors.desc_sets + 0, 0, NULL);
|
||||
vkCmdDispatch(cmdbuf, (args->width + WG_W - 1) / WG_W, (args->height + WG_H - 1) / WG_H, 1);
|
||||
}
|
||||
|
35
ref_vk/vk_ray_light_direct.h
Normal file
35
ref_vk/vk_ray_light_direct.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include "vk_core.h"
|
||||
#include "vk_rtx.h"
|
||||
#include "shaders/ray_light_direct_iface.h"
|
||||
|
||||
qboolean XVK_RayTraceLightDirectInit( void );
|
||||
void XVK_RayTraceLightDirectDestroy( void );
|
||||
void XVK_RayTraceLightDirectReloadPipeline( void );
|
||||
|
||||
typedef struct {
|
||||
uint32_t width, height;
|
||||
|
||||
struct {
|
||||
// TODO separate desc set
|
||||
VkAccelerationStructureKHR tlas;
|
||||
|
||||
// needed for alpha testing :(
|
||||
vk_buffer_region_t ubo;
|
||||
vk_buffer_region_t kusochki, indices, vertices;
|
||||
VkDescriptorImageInfo *all_textures; // [MAX_TEXTURES]
|
||||
|
||||
vk_buffer_region_t lights;
|
||||
vk_buffer_region_t light_clusters;
|
||||
|
||||
#define X(index, name, ...) VkImageView name;
|
||||
RAY_LIGHT_DIRECT_INPUTS(X)
|
||||
} in;
|
||||
|
||||
struct {
|
||||
RAY_LIGHT_DIRECT_OUTPUTS(X)
|
||||
#undef X
|
||||
} out;
|
||||
} xvk_ray_trace_light_direct_t;
|
||||
|
||||
void XVK_RayTraceLightDirect( VkCommandBuffer cmdbuf, const xvk_ray_trace_light_direct_t *args );
|
166
ref_vk/vk_rtx.c
166
ref_vk/vk_rtx.c
@ -1,6 +1,7 @@
|
||||
#include "vk_rtx.h"
|
||||
|
||||
#include "vk_ray_primary.h"
|
||||
#include "vk_ray_light_direct.h"
|
||||
|
||||
#include "vk_core.h"
|
||||
#include "vk_common.h"
|
||||
@ -94,12 +95,12 @@ typedef struct {
|
||||
|
||||
#define X(index, name, ...) xvk_image_t name;
|
||||
RAY_PRIMARY_OUTPUTS(X)
|
||||
RAY_LIGHT_DIRECT_OUTPUTS(X)
|
||||
#undef X
|
||||
|
||||
xvk_image_t diffuse_gi;
|
||||
xvk_image_t specular;
|
||||
xvk_image_t additive;
|
||||
xvk_image_t normals;
|
||||
} xvk_ray_frame_images_t;
|
||||
|
||||
static struct {
|
||||
@ -711,7 +712,7 @@ static void updateDescriptors( const vk_ray_frame_render_args_t *args, int frame
|
||||
|
||||
g_rtx.desc_values[RayDescBinding_Dest_ImageNormals].image = (VkDescriptorImageInfo){
|
||||
.sampler = VK_NULL_HANDLE,
|
||||
.imageView = frame_dst->normals.view,
|
||||
//.imageView = frame_dst->normals.view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
};
|
||||
|
||||
@ -948,11 +949,39 @@ static void performTracing( VkCommandBuffer cmdbuf, const vk_ray_frame_render_ar
|
||||
//updateDescriptors(args, frame_index, current_frame);
|
||||
|
||||
#define LIST_GBUFFER_IMAGES(X) \
|
||||
RAY_PRIMARY_OUTPUTS(X) \
|
||||
X(0, diffuse_gi) \
|
||||
X(0, specular) \
|
||||
X(0, additive) \
|
||||
X(0, normals) \
|
||||
|
||||
#define IMAGE_BARRIER(img, src_access, dst_access, old_layout, new_layout) { \
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, \
|
||||
.image = current_frame->img.image, \
|
||||
.srcAccessMask = src_access, \
|
||||
.dstAccessMask = dst_access, \
|
||||
.oldLayout = old_layout, \
|
||||
.newLayout = new_layout, \
|
||||
.subresourceRange = (VkImageSubresourceRange) { \
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, \
|
||||
.baseMipLevel = 0, \
|
||||
.levelCount = 1, \
|
||||
.baseArrayLayer = 0, \
|
||||
.layerCount = 1, \
|
||||
}, \
|
||||
},
|
||||
|
||||
#define IMAGE_BARRIER_READ(index, img, ...) \
|
||||
IMAGE_BARRIER(img, \
|
||||
VK_ACCESS_SHADER_WRITE_BIT, \
|
||||
VK_ACCESS_SHADER_READ_BIT, \
|
||||
VK_IMAGE_LAYOUT_GENERAL, \
|
||||
VK_IMAGE_LAYOUT_GENERAL)
|
||||
|
||||
#define IMAGE_BARRIER_WRITE(index, img, ...) \
|
||||
IMAGE_BARRIER(img, \
|
||||
0, \
|
||||
VK_ACCESS_SHADER_WRITE_BIT, \
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, \
|
||||
VK_IMAGE_LAYOUT_GENERAL)
|
||||
|
||||
// 4. Barrier for TLAS build and dest image layout transfer
|
||||
{
|
||||
@ -965,23 +994,10 @@ static void performTracing( VkCommandBuffer cmdbuf, const vk_ray_frame_render_ar
|
||||
.size = VK_WHOLE_SIZE,
|
||||
} };
|
||||
VkImageMemoryBarrier image_barrier[] = {
|
||||
#define GBUFFER_WRITE_BARRIER(index, img, ...) { \
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, \
|
||||
.image = current_frame->img.image, \
|
||||
.srcAccessMask = 0, \
|
||||
.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT, \
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, \
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL, \
|
||||
.subresourceRange = (VkImageSubresourceRange) { \
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, \
|
||||
.baseMipLevel = 0, \
|
||||
.levelCount = 1, \
|
||||
.baseArrayLayer = 0, \
|
||||
.layerCount = 1, \
|
||||
}, \
|
||||
},
|
||||
LIST_GBUFFER_IMAGES(GBUFFER_WRITE_BARRIER)
|
||||
LIST_GBUFFER_IMAGES(IMAGE_BARRIER_WRITE) // TODO this is not true lol
|
||||
RAY_PRIMARY_OUTPUTS(IMAGE_BARRIER_WRITE)
|
||||
};
|
||||
|
||||
vkCmdPipelineBarrier(cmdbuf,
|
||||
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
|
||||
VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
|
||||
@ -1024,48 +1040,82 @@ RAY_PRIMARY_OUTPUTS(X)
|
||||
};
|
||||
XVK_RayTracePrimary( cmdbuf, &primary_args );
|
||||
}
|
||||
|
||||
//rayTrace(cmdbuf, current_frame, fov_angle_y);
|
||||
|
||||
{
|
||||
const VkImageMemoryBarrier image_barriers[] = {
|
||||
#define GBUFFER_READ_BARRIER(index, img, ...) { \
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, \
|
||||
.image = current_frame->img.image, \
|
||||
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, \
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT, \
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, \
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL, \
|
||||
.subresourceRange = (VkImageSubresourceRange) { \
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, \
|
||||
.baseMipLevel = 0, \
|
||||
.levelCount = 1, \
|
||||
.baseArrayLayer = 0, \
|
||||
.layerCount = 1, \
|
||||
}, \
|
||||
},
|
||||
LIST_GBUFFER_IMAGES(GBUFFER_READ_BARRIER)
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.image = current_frame->denoised.image,
|
||||
.srcAccessMask = 0,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.subresourceRange =
|
||||
(VkImageSubresourceRange){
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
} };
|
||||
RAY_PRIMARY_OUTPUTS(IMAGE_BARRIER_READ)
|
||||
RAY_LIGHT_DIRECT_OUTPUTS(IMAGE_BARRIER_WRITE)
|
||||
};
|
||||
|
||||
vkCmdPipelineBarrier(args->cmdbuf,
|
||||
VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
0, 0, NULL, 0, NULL, ARRAYSIZE(image_barriers), image_barriers);
|
||||
}
|
||||
|
||||
{
|
||||
const xvk_ray_trace_light_direct_t light_direct_args = {
|
||||
.width = FRAME_WIDTH,
|
||||
.height = FRAME_HEIGHT,
|
||||
.in = {
|
||||
.tlas = g_rtx.tlas,
|
||||
.ubo = {
|
||||
.buffer = g_rtx.uniform_buffer.buffer,
|
||||
.offset = frame_index * sizeof(struct UniformBuffer),
|
||||
.size = sizeof(struct UniformBuffer),
|
||||
},
|
||||
.kusochki = {
|
||||
.buffer = g_ray_model_state.kusochki_buffer.buffer,
|
||||
.offset = 0,
|
||||
.size = g_ray_model_state.kusochki_buffer.size,
|
||||
},
|
||||
.indices = {
|
||||
.buffer = args->geometry_data.buffer,
|
||||
.offset = 0,
|
||||
.size = args->geometry_data.size,
|
||||
},
|
||||
.vertices = {
|
||||
.buffer = args->geometry_data.buffer,
|
||||
.offset = 0,
|
||||
.size = args->geometry_data.size,
|
||||
},
|
||||
.lights = {
|
||||
.buffer = g_ray_model_state.lights_buffer.buffer,
|
||||
.offset = 0,
|
||||
.size = VK_WHOLE_SIZE, // TODO multiple frames
|
||||
},
|
||||
.light_clusters = {
|
||||
.buffer = g_rtx.light_grid_buffer.buffer,
|
||||
.offset = 0,
|
||||
.size = VK_WHOLE_SIZE, // TODO multiple frames
|
||||
},
|
||||
.all_textures = tglob.dii_all_textures,
|
||||
#define X(index, name, ...) .name = current_frame->name.view,
|
||||
RAY_LIGHT_DIRECT_INPUTS(X)
|
||||
},
|
||||
.out = {
|
||||
RAY_LIGHT_DIRECT_OUTPUTS(X)
|
||||
#undef X
|
||||
},
|
||||
};
|
||||
XVK_RayTraceLightDirect( cmdbuf, &light_direct_args );
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
const VkImageMemoryBarrier image_barriers[] = {
|
||||
RAY_LIGHT_DIRECT_OUTPUTS(IMAGE_BARRIER_READ)
|
||||
LIST_GBUFFER_IMAGES(IMAGE_BARRIER_READ)
|
||||
IMAGE_BARRIER_WRITE(-1/*unused*/, denoised)
|
||||
};
|
||||
vkCmdPipelineBarrier(args->cmdbuf,
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
0, 0, NULL, 0, NULL, ARRAYSIZE(image_barriers), image_barriers);
|
||||
}
|
||||
|
||||
{
|
||||
const xvk_denoiser_args_t denoiser_args = {
|
||||
.cmdbuf = cmdbuf,
|
||||
@ -1074,7 +1124,7 @@ LIST_GBUFFER_IMAGES(GBUFFER_READ_BARRIER)
|
||||
.src = {
|
||||
.position_t_view = current_frame->position_t.view,
|
||||
.base_color_a_view = current_frame->base_color_a.view,
|
||||
.diffuse_gi_view = current_frame->diffuse_gi.view,
|
||||
.diffuse_gi_view = current_frame->light_diffuse.view,
|
||||
.specular_view = current_frame->specular.view,
|
||||
.additive_view = current_frame->additive.view,
|
||||
.normals_view = current_frame->normals_gs.view,
|
||||
@ -1136,6 +1186,7 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args)
|
||||
createPipeline();
|
||||
|
||||
XVK_RayTracePrimaryReloadPipeline();
|
||||
XVK_RayTraceLightDirectReloadPipeline();
|
||||
XVK_DenoiserReloadPipeline();
|
||||
g_rtx.reload_pipeline = false;
|
||||
}
|
||||
@ -1306,6 +1357,7 @@ qboolean VK_RayInit( void )
|
||||
// TODO complain and cleanup on failure
|
||||
|
||||
ASSERT(XVK_RayTracePrimaryInit());
|
||||
ASSERT(XVK_RayTraceLightDirectInit());
|
||||
|
||||
g_rtx.sbt_record_size = vk_core.physical_device.sbt_record_size;
|
||||
|
||||
@ -1400,7 +1452,10 @@ qboolean VK_RayInit( void )
|
||||
#define rgba32f VK_FORMAT_R32G32B32A32_SFLOAT
|
||||
#define rgba16f VK_FORMAT_R16G16B16A16_SFLOAT
|
||||
#define X(index, name, format) CREATE_GBUFFER_IMAGE(name, format, 0);
|
||||
// TODO better format for normals VK_FORMAT_R16G16B16A16_SNORM
|
||||
// TODO make sure this format and usage is suppported
|
||||
RAY_PRIMARY_OUTPUTS(X)
|
||||
RAY_LIGHT_DIRECT_OUTPUTS(X)
|
||||
#undef X
|
||||
#undef rgba8
|
||||
#undef rgba32f
|
||||
@ -1408,8 +1463,6 @@ RAY_PRIMARY_OUTPUTS(X)
|
||||
CREATE_GBUFFER_IMAGE(diffuse_gi, VK_FORMAT_R16G16B16A16_SFLOAT, 0);
|
||||
CREATE_GBUFFER_IMAGE(specular, VK_FORMAT_R16G16B16A16_SFLOAT, 0);
|
||||
CREATE_GBUFFER_IMAGE(additive, VK_FORMAT_R16G16B16A16_SFLOAT, 0);
|
||||
// TODO make sure this format and usage is suppported
|
||||
CREATE_GBUFFER_IMAGE(normals, VK_FORMAT_R16G16B16A16_SNORM, 0);
|
||||
#undef CREATE_GBUFFER_IMAGE
|
||||
}
|
||||
|
||||
@ -1423,17 +1476,18 @@ RAY_PRIMARY_OUTPUTS(X)
|
||||
void VK_RayShutdown( void ) {
|
||||
ASSERT(vk_core.rtx);
|
||||
|
||||
XVK_RayTraceLightDirectDestroy();
|
||||
XVK_RayTracePrimaryDestroy();
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(g_rtx.frames); ++i) {
|
||||
XVK_ImageDestroy(&g_rtx.frames[i].denoised);
|
||||
#define X(index, name, ...) XVK_ImageDestroy(&g_rtx.frames[i].name);
|
||||
RAY_PRIMARY_OUTPUTS(X)
|
||||
RAY_LIGHT_DIRECT_OUTPUTS(X)
|
||||
#undef X
|
||||
XVK_ImageDestroy(&g_rtx.frames[i].diffuse_gi);
|
||||
XVK_ImageDestroy(&g_rtx.frames[i].specular);
|
||||
XVK_ImageDestroy(&g_rtx.frames[i].additive);
|
||||
XVK_ImageDestroy(&g_rtx.frames[i].normals);
|
||||
}
|
||||
|
||||
vkDestroyPipeline(vk_core.device, g_rtx.pipeline, NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user