From 1cfb183cbda1bbaf8dfc5497abde2f3b13002aa5 Mon Sep 17 00:00:00 2001 From: Ivan 'provod' Avdeev Date: Mon, 1 May 2023 15:34:13 -0700 Subject: [PATCH] rt: extract per-model data from kusochki --- ref/vk/shaders/additive.rahit | 3 +- ref/vk/shaders/bounce.comp | 1 + ref/vk/shaders/light_common.glsl | 2 +- ref/vk/shaders/ray_interop.h | 25 ++++++++--------- ref/vk/shaders/ray_kusochki.glsl | 8 ++++-- ref/vk/shaders/ray_primary.comp | 1 + ref/vk/shaders/ray_primary.rchit | 5 ++-- ref/vk/shaders/ray_primary_hit.glsl | 10 +++++-- ref/vk/shaders/ray_shadow.rchit | 2 +- ref/vk/shaders/rt_geometry.glsl | 9 ++++-- ref/vk/shaders/trace_simple_blending.glsl | 29 ++++++++++--------- ref/vk/vk_ray_accel.c | 25 +++++++++++++++-- ref/vk/vk_ray_internal.h | 4 +++ ref/vk/vk_ray_model.c | 34 +++++++++-------------- ref/vk/vk_render.h | 2 +- ref/vk/vk_rtx.c | 18 ++++++++++++ 16 files changed, 110 insertions(+), 68 deletions(-) diff --git a/ref/vk/shaders/additive.rahit b/ref/vk/shaders/additive.rahit index f6633125..82eab42d 100644 --- a/ref/vk/shaders/additive.rahit +++ b/ref/vk/shaders/additive.rahit @@ -30,7 +30,8 @@ void main() { // TODO mips const uint tex_index = kusok.material.tex_base_color; const vec4 texture_color = texture(textures[nonuniformEXT(tex_index)], texture_uv); - const vec3 color = texture_color.rgb * kusok.model.color.rgb * texture_color.a * kusok.model.color.a; + const vec4 mm_color = getModelHeader(gl_InstanceID).color * kusok.material.base_color; + const vec3 color = texture_color.rgb * mm_color.rgb * texture_color.a * mm_color.a; const float overshoot = gl_HitTEXT - payload_additive.ray_distance; diff --git a/ref/vk/shaders/bounce.comp b/ref/vk/shaders/bounce.comp index 35f021fa..094f24b0 100644 --- a/ref/vk/shaders/bounce.comp +++ b/ref/vk/shaders/bounce.comp @@ -72,6 +72,7 @@ bool getHit(vec3 origin, vec3 direction, inout RayPayloadPrimary payload) { // 2. Same as the above, but also with a completely independent TLAS. Why: no need to mask-check geometry for opaque-vs-alpha const MiniGeometry geom = readCandidateMiniGeometry(rq); const uint tex_base_color = getKusok(geom.kusok_index).material.tex_base_color; + // Should never happen: skybox is opaque if (tex_base_color == TEX_BASE_SKYBOX) const vec4 texture_color = texture(textures[nonuniformEXT(tex_base_color)], geom.uv); const float alpha_mask_threshold = .1f; diff --git a/ref/vk/shaders/light_common.glsl b/ref/vk/shaders/light_common.glsl index c343caa3..01db0564 100644 --- a/ref/vk/shaders/light_common.glsl +++ b/ref/vk/shaders/light_common.glsl @@ -140,7 +140,7 @@ bool shadowedSky(vec3 pos, vec3 dir) { const uint kusok_index = instance_kusochki_offset + geometry_index; const Kusok kusok = getKusok(kusok_index); - if (kusok.material.mode != MATERIAL_MODE_SKYBOX) + if (kusok.material.tex_base_color != TEX_BASE_SKYBOX) return true; } diff --git a/ref/vk/shaders/ray_interop.h b/ref/vk/shaders/ray_interop.h index ad16f3d9..bb6bf276 100644 --- a/ref/vk/shaders/ray_interop.h +++ b/ref/vk/shaders/ray_interop.h @@ -69,15 +69,10 @@ LIST_SPECIALIZATION_CONSTANTS(DECLARE_SPECIALIZATION_CONSTANT) #define MATERIAL_MODE_BLEND_ADD 3 #define MATERIAL_MODE_BLEND_MIX 4 #define MATERIAL_MODE_BLEND_GLOW 5 -#define MATERIAL_MODE_SKYBOX 6 + +#define TEX_BASE_SKYBOX 0xffffffffu struct Material { - // TODO this should be moved to ModelMetadata, as granularity of this is per-model - // EXCEPT for skybox. Sky surfaces are all over the place in worldbrush. - // Maybe tex_base_color should have a special value for skybox. - // Moving this to model would allow us to make kusochki mostly static (except for animated textures) - uint mode; - uint tex_base_color; // TODO can be combined into a single texture @@ -92,11 +87,16 @@ struct Material { float roughness; float metalness; float normal_scale; + PAD(1) + + vec4 base_color; }; -struct ModelMetadata { - vec4 color; +struct ModelHeader { mat4 prev_transform; + vec4 color; + uint mode; + PAD(3) }; struct Kusok { @@ -109,15 +109,12 @@ struct Kusok { // Alignt it here to vec4 explicitly, so that later vector fields are properly aligned (for simplicity). uint _padding0; - // TODO reference into material table - STRUCT Material material; - // Per-kusok because individual surfaces can be patched vec3 emissive; PAD(1) - // TODO move into a separate model array, and reference it by gl_GeometryIndexEXT/rayQueryGetIntersectionGeometryIndexEXT - STRUCT ModelMetadata model; + // TODO reference into material table + STRUCT Material material; }; struct PointLight { diff --git a/ref/vk/shaders/ray_kusochki.glsl b/ref/vk/shaders/ray_kusochki.glsl index af0110fe..6bb3ff8a 100644 --- a/ref/vk/shaders/ray_kusochki.glsl +++ b/ref/vk/shaders/ray_kusochki.glsl @@ -16,12 +16,14 @@ struct Vertex { uint color; }; -layout(std430, binding = 3, set = 0) readonly buffer Kusochki { Kusok a[]; } kusochki; -layout(std430, binding = 4, set = 0) readonly buffer Indices { uint16_t a[]; } indices; -layout(std430, binding = 5, set = 0) readonly buffer Vertices { Vertex a[]; } vertices; +layout(std430, binding = 30, set = 0) readonly buffer ModelHeaders { ModelHeader a[]; } model_headers; +layout(std430, binding = 31, set = 0) readonly buffer Kusochki { Kusok a[]; } kusochki; +layout(std430, binding = 32, set = 0) readonly buffer Indices { uint16_t a[]; } indices; +layout(std430, binding = 33, set = 0) readonly buffer Vertices { Vertex a[]; } vertices; Kusok getKusok(uint index) { return kusochki.a[index]; } uint16_t getIndex(uint index) { return indices.a[index]; } +ModelHeader getModelHeader(uint index) { return model_headers.a[index]; } #define GET_VERTEX(index) (vertices.a[index]) #endif //ifndef RAY_KUSOCHKI_GLSL_INCLUDED diff --git a/ref/vk/shaders/ray_primary.comp b/ref/vk/shaders/ray_primary.comp index 2f164627..ec2465cd 100644 --- a/ref/vk/shaders/ray_primary.comp +++ b/ref/vk/shaders/ray_primary.comp @@ -87,6 +87,7 @@ void main() { // 2. Same as the above, but also with a completely independent TLAS. Why: no need to mask-check geometry for opaque-vs-alpha const MiniGeometry geom = readCandidateMiniGeometry(rq); const uint tex_base_color = getKusok(geom.kusok_index).material.tex_base_color; + // Should never happen: skybox is opaque if (tex_base_color == TEX_BASE_SKYBOX) const vec4 texture_color = texture(textures[nonuniformEXT(tex_base_color)], geom.uv); const float alpha_mask_threshold = .1f; diff --git a/ref/vk/shaders/ray_primary.rchit b/ref/vk/shaders/ray_primary.rchit index 4c17b605..d52a9e53 100644 --- a/ref/vk/shaders/ray_primary.rchit +++ b/ref/vk/shaders/ray_primary.rchit @@ -29,11 +29,12 @@ void main() { const Kusok kusok = getKusok(geom.kusok_index); - if (kusok.material.mode == MATERIAL_MODE_SKYBOX) { + if (kusok.material.tex_base_color == TEX_BASE_SKYBOX) { payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, gl_WorldRayDirectionEXT).rgb); return; } else { - payload.base_color_a = sampleTexture(kusok.material.tex_base_color, geom.uv, geom.uv_lods) * kusok.model.color; + const vec4 color = getModelHeader(gl_InstanceID).color * kusok.material.base_color; + payload.base_color_a = sampleTexture(kusok.material.tex_base_color, geom.uv, geom.uv_lods) * color; payload.material_rmxx.r = sampleTexture(kusok.material.tex_roughness, geom.uv, geom.uv_lods).r * kusok.material.roughness; payload.material_rmxx.g = sampleTexture(kusok.material.tex_metalness, geom.uv, geom.uv_lods).r * kusok.material.metalness; diff --git a/ref/vk/shaders/ray_primary_hit.glsl b/ref/vk/shaders/ray_primary_hit.glsl index 9f7d157e..1a115042 100644 --- a/ref/vk/shaders/ray_primary_hit.glsl +++ b/ref/vk/shaders/ray_primary_hit.glsl @@ -30,7 +30,7 @@ void primaryRayHit(rayQueryEXT rq, inout RayPayloadPrimary payload) { const Kusok kusok = getKusok(geom.kusok_index); const Material material = kusok.material; - if (kusok.material.mode == MATERIAL_MODE_SKYBOX) { + if (kusok.material.tex_base_color == TEX_BASE_SKYBOX) { payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, rayDirection).rgb); return; } else { @@ -69,8 +69,12 @@ void primaryRayHit(rayQueryEXT rq, inout RayPayloadPrimary payload) { payload.emissive.rgb *= payload.base_color_a.rgb; #endif - payload.base_color_a *= kusok.model.color; - payload.emissive.rgb *= kusok.model.color.rgb; + const int model_index = rayQueryGetIntersectionInstanceIdEXT(rq, true); + const ModelHeader model = getModelHeader(model_index); + const vec4 color = model.color * kusok.material.base_color; + + payload.base_color_a *= color; + payload.emissive.rgb *= color.rgb; } #endif // ifndef RAY_PRIMARY_HIT_GLSL_INCLUDED diff --git a/ref/vk/shaders/ray_shadow.rchit b/ref/vk/shaders/ray_shadow.rchit index bf7629cb..b63f7208 100644 --- a/ref/vk/shaders/ray_shadow.rchit +++ b/ref/vk/shaders/ray_shadow.rchit @@ -12,5 +12,5 @@ void main() { const Kusok kusok = getKusok(kusok_index); const uint tex_base_color = kusok.material.tex_base_color; - payload_shadow.hit_type = (kusok.material.mode != MATERIAL_MODE_SKYBOX) ? SHADOW_HIT : SHADOW_SKY ; + payload_shadow.hit_type = (kusok.material.tex_base_color != TEX_BASE_SKYBOX) ? SHADOW_HIT : SHADOW_SKY ; } diff --git a/ref/vk/shaders/rt_geometry.glsl b/ref/vk/shaders/rt_geometry.glsl index 0f1de351..2be93f4c 100644 --- a/ref/vk/shaders/rt_geometry.glsl +++ b/ref/vk/shaders/rt_geometry.glsl @@ -56,6 +56,7 @@ struct Geometry { #ifdef RAY_QUERY Geometry readHitGeometry(rayQueryEXT rq, float ray_cone_width, vec2 bary) { + const int model_index = rayQueryGetIntersectionInstanceIdEXT(rq, true); const int instance_kusochki_offset = rayQueryGetIntersectionInstanceCustomIndexEXT(rq, true); const int geometry_index = rayQueryGetIntersectionGeometryIndexEXT(rq, true); const int primitive_index = rayQueryGetIntersectionPrimitiveIndexEXT(rq, true); @@ -64,6 +65,7 @@ Geometry readHitGeometry(rayQueryEXT rq, float ray_cone_width, vec2 bary) { const float hit_t = rayQueryGetIntersectionTEXT(rq, true); #else Geometry readHitGeometry(vec2 bary, float ray_cone_width) { + const int model_index = gl_InstanceID; const int instance_kusochki_offset = gl_InstanceCustomIndexEXT; const int geometry_index = gl_GeometryIndexEXT; const int primitive_index = gl_PrimitiveID; @@ -88,10 +90,11 @@ Geometry readHitGeometry(vec2 bary, float ray_cone_width) { objectToWorld * vec4(GET_VERTEX(vi3).pos, 1.f), }; + const ModelHeader model = getModelHeader(model_index); const vec3 prev_pos[3] = { - (kusok.model.prev_transform * vec4(GET_VERTEX(vi1).prev_pos, 1.f)).xyz, - (kusok.model.prev_transform * vec4(GET_VERTEX(vi2).prev_pos, 1.f)).xyz, - (kusok.model.prev_transform * vec4(GET_VERTEX(vi3).prev_pos, 1.f)).xyz, + (model.prev_transform * vec4(GET_VERTEX(vi1).prev_pos, 1.f)).xyz, + (model.prev_transform * vec4(GET_VERTEX(vi2).prev_pos, 1.f)).xyz, + (model.prev_transform * vec4(GET_VERTEX(vi3).prev_pos, 1.f)).xyz, }; const vec2 uvs[3] = { diff --git a/ref/vk/shaders/trace_simple_blending.glsl b/ref/vk/shaders/trace_simple_blending.glsl index d5079292..3afcc365 100644 --- a/ref/vk/shaders/trace_simple_blending.glsl +++ b/ref/vk/shaders/trace_simple_blending.glsl @@ -27,44 +27,43 @@ void traceSimpleBlending(vec3 pos, vec3 dir, float L, inout vec3 emissive, inout rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_BLEND, pos, 0., dir, L + glow_soft_overshoot); while (rayQueryProceedEXT(rq)) { const MiniGeometry geom = readCandidateMiniGeometry(rq); + const int model_index = rayQueryGetIntersectionInstanceIdEXT(rq, false); + const ModelHeader model = getModelHeader(model_index); const Kusok kusok = getKusok(geom.kusok_index); const float hit_t = rayQueryGetIntersectionTEXT(rq, false); const float overshoot = hit_t - L; - if (overshoot > 0. && kusok.material.mode != MATERIAL_MODE_BLEND_GLOW) + if (overshoot > 0. && model.mode != MATERIAL_MODE_BLEND_GLOW) continue; //#define DEBUG_BLEND_MODES #ifdef DEBUG_BLEND_MODES - if (kusok.material.mode == MATERIAL_MODE_BLEND_GLOW) { + if (model.mode == MATERIAL_MODE_BLEND_GLOW) { emissive += vec3(1., 0., 0.); //ret += color * smoothstep(glow_soft_overshoot, 0., overshoot); - } else if (kusok.material.mode == MATERIAL_MODE_BLEND_ADD) { + } else if (model.mode == MATERIAL_MODE_BLEND_ADD) { emissive += vec3(0., 1., 0.); - } else if (kusok.material.mode == MATERIAL_MODE_BLEND_MIX) { + } else if (model.mode == MATERIAL_MODE_BLEND_MIX) { emissive += vec3(0., 0., 1.); - } else if (kusok.material.mode == MATERIAL_MODE_TRANSLUCENT) { + } else if (model.mode == MATERIAL_MODE_TRANSLUCENT) { emissive += vec3(0., 1., 1.); - } else if (kusok.material.mode == MATERIAL_MODE_OPAQUE) { + } else if (model.mode == MATERIAL_MODE_OPAQUE) { emissive += vec3(1., 1., 1.); } #else const vec4 texture_color = texture(textures[nonuniformEXT(kusok.material.tex_base_color)], geom.uv); + const vec4 mm_color = model.color * kusok.material.base_color; + float alpha = mm_color.a * texture_color.a * geom.vertex_color.a; + vec3 color = mm_color.rgb * SRGBtoLINEAR(texture_color.rgb) * geom.vertex_color.rgb * alpha; - // "Linearizing" alpha, while looking weird conceptually in the code, is necessary to make it look close to the original. - // TODO figure out whether texture alpha needs to be linearized too. Don't have good examples to look at. - // TODO this also makes sprites look dull, so likely kusok.model.color linearization should only apply to brush models, not sprites. This is better done when passing brush model to ray tracer. - float alpha = SRGBtoLINEAR(texture_color.a * kusok.model.color.a) * geom.vertex_color.a; - vec3 color = kusok.model.color.rgb * SRGBtoLINEAR(texture_color.rgb) * geom.vertex_color.rgb * alpha; - - if (kusok.material.mode == MATERIAL_MODE_BLEND_GLOW) { + if (model.mode == MATERIAL_MODE_BLEND_GLOW) { // Glow is additive + small overshoot const float overshoot_factor = smoothstep(glow_soft_overshoot, 0., overshoot); color *= overshoot_factor; alpha = 0.; - } else if (kusok.material.mode == MATERIAL_MODE_BLEND_ADD) { + } else if (model.mode == MATERIAL_MODE_BLEND_ADD) { // Additive doesn't attenuate what's behind alpha = 0.; - } else if (kusok.material.mode == MATERIAL_MODE_BLEND_MIX) { + } else if (model.mode == MATERIAL_MODE_BLEND_MIX) { // Handled in composite step below } else { // Signal unhandled blending type diff --git a/ref/vk/vk_ray_accel.c b/ref/vk/vk_ray_accel.c index 77ca702e..c9d0ad7d 100644 --- a/ref/vk/vk_ray_accel.c +++ b/ref/vk/vk_ray_accel.c @@ -5,6 +5,10 @@ #include "vk_ray_internal.h" #include "r_speeds.h" #include "vk_combuf.h" +#include "vk_staging.h" +#include "vk_math.h" + +#include "xash3d_mathlib.h" #define MAX_SCRATCH_BUFFER (32*1024*1024) #define MAX_ACCELS_BUFFER (64*1024*1024) @@ -178,6 +182,15 @@ void RT_VkAccelPrepareTlas(vk_combuf_t *combuf) { // Upload all blas instances references to GPU mem { + const vk_staging_region_t headers_lock = R_VkStagingLockForBuffer((vk_staging_buffer_args_t){ + .buffer = g_ray_model_state.model_headers_buffer.buffer, + .offset = 0, + .size = g_ray_model_state.frame.num_models * sizeof(struct ModelHeader), + .alignment = 16, + }); + + ASSERT(headers_lock.ptr); + VkAccelerationStructureInstanceKHR* inst = ((VkAccelerationStructureInstanceKHR*)g_accel.tlas_geom_buffer.mapped) + instance_offset; for (int i = 0; i < g_ray_model_state.frame.num_models; ++i) { const vk_ray_draw_model_t* const model = g_ray_model_state.frame.models + i; @@ -190,7 +203,6 @@ void RT_VkAccelPrepareTlas(vk_combuf_t *combuf) { }; switch (model->material_mode) { case MATERIAL_MODE_OPAQUE: - case MATERIAL_MODE_SKYBOX: inst[i].mask = GEOMETRY_BIT_OPAQUE; inst[i].instanceShaderBindingTableRecordOffset = SHADER_OFFSET_HIT_REGULAR, inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR; @@ -217,7 +229,14 @@ void RT_VkAccelPrepareTlas(vk_combuf_t *combuf) { break; } memcpy(&inst[i].transform, model->transform_row, sizeof(VkTransformMatrixKHR)); + + struct ModelHeader *const header = ((struct ModelHeader*)headers_lock.ptr) + i; + header->mode = model->material_mode; + Vector4Copy(model->model->color, header->color); + Matrix4x4_ToArrayFloatGL(model->model->prev_transform, (float*)header->prev_transform); } + + R_VkStagingUnlock(headers_lock.handle); } g_accel_.stats.blas_count = g_ray_model_state.frame.num_models; @@ -225,14 +244,14 @@ void RT_VkAccelPrepareTlas(vk_combuf_t *combuf) { // Barrier for building all BLASes // BLAS building is now in cmdbuf, need to synchronize with results { - VkBufferMemoryBarrier bmb[] = { { + VkBufferMemoryBarrier bmb[] = {{ .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, .srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, // | VK_ACCESS_TRANSFER_WRITE_BIT, .dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, .buffer = g_accel.accels_buffer.buffer, .offset = instance_offset * sizeof(VkAccelerationStructureInstanceKHR), .size = g_ray_model_state.frame.num_models * sizeof(VkAccelerationStructureInstanceKHR), - } }; + }}; vkCmdPipelineBarrier(combuf->cmdbuf, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, diff --git a/ref/vk/vk_ray_internal.h b/ref/vk/vk_ray_internal.h index 911e0b2b..f1054bad 100644 --- a/ref/vk/vk_ray_internal.h +++ b/ref/vk/vk_ray_internal.h @@ -60,6 +60,10 @@ typedef struct { vk_buffer_t kusochki_buffer; r_debuffer_t kusochki_alloc; + // Model header + // Array of struct ModelHeader: color, material_mode, prev_transform + vk_buffer_t model_headers_buffer; + // Per-frame data that is accumulated between RayFrameBegin and End calls struct { int num_models; diff --git a/ref/vk/vk_ray_model.c b/ref/vk/vk_ray_model.c index 50a6a724..ab6699fe 100644 --- a/ref/vk/vk_ray_model.c +++ b/ref/vk/vk_ray_model.c @@ -155,7 +155,7 @@ void XVK_RayModel_Validate( void ) { } } -static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometry_t *geom, const vec4_t model_color, uint32_t mode) { +static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometry_t *geom) { const xvk_material_t *const mat = XVK_GetMaterialForTextureIndex( geom->texture ); ASSERT(mat); @@ -165,9 +165,8 @@ static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometr kusok->index_offset = geom->index_offset; kusok->triangles = geom->element_count / 3; + // Material data itself is mostly static. Except for animated textures, which just get a new material slot for each frame. kusok->material = (struct Material){ - .mode = mode, - .tex_base_color = mat->tex_base_color, .tex_roughness = mat->tex_roughness, .tex_metalness = mat->tex_metalness, @@ -178,24 +177,18 @@ static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometr .normal_scale = mat->normal_scale, }; + // TODO emissive is potentially "dynamic", not tied to the material directly, as it is specified per-surface in rad files + VectorCopy(geom->emissive, kusok->emissive); + Vector4Copy(mat->base_color, kusok->material.base_color); + + // TODO should be patched by the Chrome material source itself to generate a static chrome material const qboolean HACK_chrome = geom->material == kXVkMaterialChrome; if (!mat->set && HACK_chrome) kusok->material.tex_roughness = tglob.grayTexture; + // Purely static. Once a sky forever a sky. if (geom->material == kXVkMaterialSky) - kusok->material.mode = MATERIAL_MODE_SKYBOX; - - // FIXME modulates model_color with material->base_color which has different frequency - { - vec4_t gcolor; - gcolor[0] = model_color[0] * mat->base_color[0]; - gcolor[1] = model_color[1] * mat->base_color[1]; - gcolor[2] = model_color[2] * mat->base_color[2]; - gcolor[3] = model_color[3] * mat->base_color[3]; - Vector4Copy(gcolor, kusok->model.color); - } - - VectorCopy(geom->emissive, kusok->emissive); + kusok->material.tex_base_color = TEX_BASE_SKYBOX; } vk_ray_model_t* VK_RayModelCreate( vk_ray_model_init_t args ) { @@ -329,7 +322,7 @@ void VK_RayModelDestroy( struct vk_ray_model_s *model ) { } } -// TODO move this to some common place with traditional renderer +// TODO move this to vk_brush static void computeConveyorSpeed(const color24 rendercolor, int tex_index, vec2_t speed) { float sy, cy; float flConveyorSpeed = 0.0f; @@ -358,6 +351,7 @@ static void computeConveyorSpeed(const color24 rendercolor, int tex_index, vec2_ speed[1] = sy * flRate; } +// TODO utilize uploadKusochki([1]) to avoid 2 copies of staging code static qboolean uploadKusochkiSubset(const vk_ray_model_t *const model, const vk_render_model_t *const render_model, uint32_t material_mode, const int *geom_indexes, int geom_indexes_count) { // TODO can we sort all animated geometries (in brush) to have only a single range here? for (int i = 0; i < geom_indexes_count; ++i) { @@ -379,8 +373,7 @@ static qboolean uploadKusochkiSubset(const vk_ray_model_t *const model, const vk vk_kusok_data_t *const kusochki = kusok_staging.ptr; vk_render_geometry_t *geom = render_model->geometries + index; - applyMaterialToKusok(kusochki + 0, geom, render_model->color, material_mode); - Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)(kusochki + 0)->model.prev_transform); + applyMaterialToKusok(kusochki + 0, geom); /* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */ /* render_model->debug_name, */ @@ -413,8 +406,7 @@ static qboolean uploadKusochki(const vk_ray_model_t *const model, const vk_rende for (int i = 0; i < render_model->num_geometries; ++i) { vk_render_geometry_t *geom = render_model->geometries + i; - applyMaterialToKusok(kusochki + i, geom, render_model->color, material_mode); - Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)(kusochki + i)->model.prev_transform); + applyMaterialToKusok(kusochki + i, geom); } /* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */ diff --git a/ref/vk/vk_render.h b/ref/vk/vk_render.h index 6b7df028..37dc537e 100644 --- a/ref/vk/vk_render.h +++ b/ref/vk/vk_render.h @@ -25,7 +25,7 @@ typedef enum { kXVkMaterialRegular = 0, // Set for SURF_DRAWSKY surfaces in vk_brush.c. - // Used: for setting MATERIAL_MODE_SKYBOX for skybox texture sampling and environment shadows. + // Used: for setting TEX_BASE_SKYBOX for skybox texture sampling and environment shadows. // Remove: pass it as a special texture/material index (e.g. -2). kXVkMaterialSky, diff --git a/ref/vk/vk_rtx.c b/ref/vk/vk_rtx.c index 2089706d..fafdd40a 100644 --- a/ref/vk/vk_rtx.c +++ b/ref/vk/vk_rtx.c @@ -45,6 +45,7 @@ X(TLAS, tlas) \ X(Buffer, ubo) \ X(Buffer, kusochki) \ + X(Buffer, model_headers) \ X(Buffer, indices) \ X(Buffer, vertices) \ X(Buffer, lights) \ @@ -201,6 +202,7 @@ static void performTracing( vk_combuf_t *combuf, const perform_tracing_args_t* a // TODO move this to ray model producer RES_SET_SBUFFER_FULL(kusochki, g_ray_model_state.kusochki_buffer); + RES_SET_SBUFFER_FULL(model_headers, g_ray_model_state.model_headers_buffer); // TODO move these to vk_geometry RES_SET_SBUFFER_FULL(indices, args->render_args->geometry_data); @@ -221,6 +223,13 @@ static void performTracing( vk_combuf_t *combuf, const perform_tracing_args_t* a .buffer = g_ray_model_state.kusochki_buffer.buffer, .offset = 0, .size = VK_WHOLE_SIZE, + }, { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + .buffer = g_ray_model_state.model_headers_buffer.buffer, + .offset = 0, + .size = VK_WHOLE_SIZE, } }; vkCmdPipelineBarrier(cmdbuf, @@ -631,6 +640,14 @@ qboolean VK_RayInit( void ) // FIXME complain, handle return false; } + + if (!VK_BufferCreate("model headers", &g_ray_model_state.model_headers_buffer, sizeof(struct ModelHeader) * MAX_ACCELS, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) { + // FIXME complain, handle + return false; + } + RT_RayModel_Clear(); gEngine.Cmd_AddCommand("vk_rtx_reload", reloadPipeline, "Reload RTX shader"); @@ -643,6 +660,7 @@ void VK_RayShutdown( void ) { destroyMainpipe(); + VK_BufferDestroy(&g_ray_model_state.model_headers_buffer); VK_BufferDestroy(&g_ray_model_state.kusochki_buffer); VK_BufferDestroy(&g_rtx.uniform_buffer);