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:
Ivan Avdeev 2022-01-10 19:13:08 -08:00
parent b9760aaaea
commit af24afbcc3
11 changed files with 562 additions and 67 deletions

View File

@ -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
View 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
}

View File

@ -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)

View File

@ -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);

View File

@ -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

View 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));
}

View 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) \

View File

@ -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;

View 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);
}

View 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 );

View File

@ -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);