Merge pull request #559 from w23/bluenoise

vk: textures: add blue noise textures
This commit is contained in:
NightFox 2023-10-04 22:55:53 +03:00 committed by GitHub
commit e04a19a0af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 161 additions and 3 deletions

View File

@ -399,6 +399,19 @@ TODO: can we not have a BLAS/model for each submodel? Can it be per-model instea
- ~~R_DrawStudioModel is the main func for drawing studio model. Called from scene code for each studio entity, with everything current (RI and stuff) set up~~
- `R_StudioDrawModelInternal()` is the main one. It is where it splits into renderer-vs-game rendering functions.
# 2023-09-11 E293
- light shaders include structure
- ray_light_direct_{poly,point}.comp
- ray_light_direct.glsl
- utils.glsl
- noise.glsl
- ray_interop.h
- ray_kusochki.glsl
- light.glsl
- brdf.h
- light_common.glsl
- LIGHT_POLYGON: light_polygon.glsl
# 2023-09-19 E298
## SURF_DRAWSKY
- (context: want to remove kXVkMaterialSky, #474)

22
ref/vk/pcg.h Normal file
View File

@ -0,0 +1,22 @@
// *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
#pragma once
#include <stdint.h>
typedef struct { uint64_t state; uint64_t inc; } pcg32_random_t;
uint32_t pcg32_random_r(pcg32_random_t* rng);
#if defined(PCG_IMPLEMENT)
uint32_t pcg32_random_r(pcg32_random_t* rng)
{
uint64_t oldstate = rng->state;
// Advance internal state
rng->state = oldstate * 6364136223846793005ULL + (rng->inc|1);
// Calculate output function (XSH RR), uses old state for max ILP
uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
uint32_t rot = oldstate >> 59u;
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
}
#endif

View File

@ -0,0 +1,20 @@
#ifndef BLUENOISE_H_INCLUDED
#define BLUENOISE_H_INCLUDED
// Depends on uniform sampler2D textures[MAX_TEXTURES] binding being defined
// This is the same hardcoded value as in vk_textures.h
// Please keep them in sync onegai uwu
// TODO:
// - make bluenoise texture a separate binding, not part of textures[] array
// - make it a 3D texture
#define BLUE_NOISE_TEXTURE_BEGIN 6
// Also see vk_textures.h, keep in sync, etc etc
#define BLUE_NOISE_SIZE 64
vec4 blueNoise(ivec3 v) {
v %= BLUE_NOISE_SIZE;
return texelFetch(textures[BLUE_NOISE_TEXTURE_BEGIN+v.z], v.xy, 0);
}
#endif // ifndef BLUENOISE_H_INCLUDED

View File

@ -36,6 +36,10 @@ layout(set = 0, binding = 15, rgba16f) uniform image2D prev_temporal_diffuse;
layout(set = 0, binding = 16, rgba16f) uniform image2D out_temporal_specular;
layout(set = 0, binding = 17, rgba16f) uniform image2D prev_temporal_specular;
#ifdef DEBUG_NOISE
layout(set = 0, binding = 18) uniform sampler2D textures[MAX_TEXTURES];
include "bluenoise.glsl"
#endif
const int INDIRECT_SCALE = 2;
@ -185,6 +189,10 @@ void main() {
return;
}
#ifdef DEBUG_NOISE
imageStore(out_dest, pix, blueNoise(ivec3(pix.xy, ubo.ubo.frame_counter))); return;
#endif
/* if (pix.y < res.y / 3) { */
/* imageStore(out_dest, pix, vec4(pow(float(pix.x) / res.x, 2.2))); return; */
/* } else if (pix.y < res.y * 2 / 3) { */

View File

@ -173,7 +173,8 @@ struct UniformBuffer {
mat4 prev_inv_proj, prev_inv_view;
float ray_cone_width;
uint random_seed;
PAD(2)
uint frame_counter;
PAD(1)
};
#undef PAD

View File

@ -140,7 +140,7 @@ void VK_RayFrameBegin( void ) {
RT_LightsFrameBegin();
}
static void prepareUniformBuffer( const vk_ray_frame_render_args_t *args, int frame_index, float fov_angle_y ) {
static void prepareUniformBuffer( const vk_ray_frame_render_args_t *args, int frame_index, uint32_t frame_counter, float fov_angle_y ) {
struct UniformBuffer *ubo = (struct UniformBuffer*)((char*)g_rtx.uniform_buffer.mapped + frame_index * g_rtx.uniform_unit_size);
matrix4x4 proj_inv, view_inv;
@ -160,11 +160,13 @@ static void prepareUniformBuffer( const vk_ray_frame_render_args_t *args, int fr
ubo->ray_cone_width = atanf((2.0f*tanf(DEG2RAD(fov_angle_y) * 0.5f)) / (float)FRAME_HEIGHT);
ubo->random_seed = (uint32_t)gEngine.COM_RandomLong(0, INT32_MAX);
ubo->frame_counter = frame_counter;
}
typedef struct {
const vk_ray_frame_render_args_t* render_args;
int frame_index;
uint32_t frame_counter;
float fov_angle_y;
const vk_lights_bindings_t *light_bindings;
} perform_tracing_args_t;
@ -271,7 +273,7 @@ static void performTracing( vk_combuf_t *combuf, const perform_tracing_args_t* a
// TODO move this to "TLAS producer"
g_rtx.res[ExternalResource_tlas].resource = RT_VkAccelPrepareTlas(combuf);
prepareUniformBuffer(args->render_args, args->frame_index, args->fov_angle_y);
prepareUniformBuffer(args->render_args, args->frame_index, args->frame_counter, args->fov_angle_y);
{ // FIXME this should be done automatically inside meatpipe, TODO
//const uint32_t size = sizeof(struct Lights);
@ -571,6 +573,7 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args)
const perform_tracing_args_t trace_args = {
.render_args = args,
.frame_index = (g_rtx.frame_number % 2),
.frame_counter = g_rtx.frame_number,
.fov_angle_y = args->fov_angle_y,
.light_bindings = &light_bindings,
};

View File

@ -15,6 +15,9 @@
#include "com_strings.h"
#include "eiface.h"
#define PCG_IMPLEMENT
#include "pcg.h"
#include <memory.h>
#include <math.h>
@ -262,6 +265,84 @@ static void VK_ProcessImage( vk_texture_t *tex, rgbdata_t *pic )
static qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, qboolean cubemap);
static int VK_LoadTextureF(int flags, const char *fmt, ...) {
int tex_id = 0;
char buffer[1024];
va_list argptr;
va_start( argptr, fmt );
vsnprintf( buffer, sizeof buffer, fmt, argptr );
va_end( argptr );
return VK_LoadTexture(buffer, NULL, 0, flags);
}
#define BLUE_NOISE_NAME_F "bluenoise/LDR_RGBA_%d.png"
static qboolean generateFallbackNoiseTextures(void) {
pcg32_random_t pcg_state = {
BLUE_NOISE_SIZE * BLUE_NOISE_SIZE - 1,
17,
};
uint32_t scratch[BLUE_NOISE_SIZE * BLUE_NOISE_SIZE];
rgbdata_t pic = {
.width = BLUE_NOISE_SIZE,
.height = BLUE_NOISE_SIZE,
.depth = 1,
.flags = 0,
.type = PF_RGBA_32,
.size = BLUE_NOISE_SIZE * BLUE_NOISE_SIZE * 4,
.buffer = (byte*)&scratch,
.palette = NULL,
.numMips = 1,
.encode = 0,
};
int blueNoiseTexturesBegin = -1;
for (int i = 0; i < BLUE_NOISE_SIZE; ++i) {
for (int j = 0; j < COUNTOF(scratch); ++j) {
scratch[j] = pcg32_random_r(&pcg_state);
}
char name[256];
snprintf(name, sizeof(name), BLUE_NOISE_NAME_F, i);
const int texid = VK_LoadTextureInternal(name, &pic, TF_NOMIPMAP);
ASSERT(texid > 0);
if (blueNoiseTexturesBegin == -1) {
ASSERT(texid == BLUE_NOISE_TEXTURE_ID);
blueNoiseTexturesBegin = texid;
} else {
ASSERT(blueNoiseTexturesBegin + i == texid);
}
}
return true;
}
static qboolean loadBlueNoiseTextures(void) {
int blueNoiseTexturesBegin = -1;
for (int i = 0; i < 64; ++i) {
const int texid = VK_LoadTextureF(TF_NOMIPMAP, BLUE_NOISE_NAME_F, i);
if (blueNoiseTexturesBegin == -1) {
if (texid <= 0) {
ERR("Couldn't find precomputed blue noise textures. Generating bad quality regular noise textures as a fallback");
return generateFallbackNoiseTextures();
}
blueNoiseTexturesBegin = texid;
} else {
ASSERT(texid > 0);
ASSERT(blueNoiseTexturesBegin + i == texid);
}
}
INFO("Base blue noise texture is %d", blueNoiseTexturesBegin);
ASSERT(blueNoiseTexturesBegin == BLUE_NOISE_TEXTURE_ID);
return true;
}
static void VK_CreateInternalTextures( void )
{
int dx2, dy, d;
@ -338,6 +419,8 @@ static void VK_CreateInternalTextures( void )
uploadTexture( &tglob.cubemap_placeholder, sides, 6, true );
}
loadBlueNoiseTextures();
}
static VkFormat VK_GetFormat(pixformat_t format) {

View File

@ -41,6 +41,14 @@ typedef struct vk_textures_global_s
int dlightTexture; // custom dlight texture
int cinTexture; // cinematic texture
// Hardcoded expected blue noise texture slot
// TODO consider moving it into a separate resource bindable by request
// TODO make it a 3D texture. Currently it's just a sequence of BLUE_NOISE_SIZE textures, loaded into consecutive slots.
#define BLUE_NOISE_TEXTURE_ID 6
// Hardcode blue noise texture size to 64x64x64
#define BLUE_NOISE_SIZE 64
qboolean fCustomSkybox; // TODO do we need this for anything?
vk_texture_t skybox_cube;