From 04db6b0ccd81d988cfe3a1d09e4eb00eeea77273 Mon Sep 17 00:00:00 2001 From: quou Date: Sat, 22 Feb 2025 17:01:35 +1100 Subject: basic shadows --- c2.cpp | 10 +++---- camera.cpp | 24 +++++++++++++++ camera.hpp | 20 +++++++++++++ intermediate/surface.glsl | 68 +++++++++++++++++++++++++++++++++++++++++- lighting.cpp | 76 +++++++++++++++++++++++++++++++++++++++-------- lighting.hpp | 30 +++++++++++++------ maths.cpp | 28 +++++++++-------- maths.hpp | 1 + model.cpp | 17 ++++++++++- model.hpp | 7 ++++- renderer.cpp | 21 +++++++++---- renderer.hpp | 15 ++-------- sc/sc.cpp | 6 ++++ video.cpp | 26 +++++++++++++++- video.hpp | 5 ++-- 15 files changed, 292 insertions(+), 62 deletions(-) diff --git a/c2.cpp b/c2.cpp index d5b262a..761d9de 100644 --- a/c2.cpp +++ b/c2.cpp @@ -754,7 +754,7 @@ struct C2 : public App { auto sun = world->create_entity(); auto [light] = world->add(sun); light.colour = v3f(1.0f, 0.95f, 0.80f); - light.dir = v3f(0.57f, 0.57f, 0.57f); + light.dir = v3f(-0.57f, 0.57f, 0.57f); light.brightness = 1.0f; light.caster = true; } @@ -889,15 +889,15 @@ struct C2 : public App { renderer.env_cubemap = eprobe.get_cubemap(); renderer.clamped_linear = clamped_linear; - renderer.drawlists[FORWARD].camera = camera; - renderer.drawlists[SHADOW_MAP_START].camera = camera; + renderer.setcam(FORWARD, camera); Texture& bb = dev->get_texture(hdr_target); pcam.asp = (float)bb.w / (float)bb.h; orbit_cam.update_orbit(*this); pcam.update(); - lighting.update(dev, ctx, *world); + lighting.update(dev, ctx, *world, renderer, scene); update_scene(scene, dev, lighting, pcam, *world); + lr.add_box(scene.bound); ctx.debug_push("scene"); renderer.render( dev, @@ -1004,7 +1004,7 @@ struct C2 : public App { quad.destroy(dev); scene.destroy(dev); sky.destroy(dev); - lighting.destroy(dev); + lighting.destroy(dev, renderer); lr.destroy(dev); eprobe.destroy(dev); tonemap.destroy(dev); diff --git a/camera.cpp b/camera.cpp index 59a604e..a224fb3 100644 --- a/camera.cpp +++ b/camera.cpp @@ -9,6 +9,30 @@ void Camera::init(float vfov, const v3f& f, const v3f& p) { asp = 1.0f; } +void Camera::init_shadow( + const v3f& dir, + const v3f& mic, + const v3f& mac +) { + v3f up(0.0f, 1.0f, 0.0f); + AABB aabb = { mic, mac }; + init(0.0f, dir, v3f(0.0f)); + view = m4f::lookat( + dir, + v3f(0.0f), + up + ); + aabb = m4f::transform(view, aabb); + proj = m4f::orth( + aabb.min.x, + aabb.max.x, + aabb.max.y, + aabb.min.y, + aabb.min.z, + aabb.max.z + ); +} + void Camera::update() { v3f up(0.0f, 1.0f, 0.0f); view = m4f::lookat(position, position + forward, up); diff --git a/camera.hpp b/camera.hpp index f88b4fe..15537f0 100644 --- a/camera.hpp +++ b/camera.hpp @@ -1,16 +1,36 @@ #ifndef camera_hpp #define camera_hpp +#include "hashmap.hpp" #include "maths.hpp" +#include "video.hpp" struct Camera { float fov, near, far, asp; v3f forward, position; m4f view, proj; + int type; void init(float vfov, const v3f& f, const v3f& p); + void init_shadow( + const v3f& dir, + const v3f& mic, + const v3f& mac + ); void update(); const m4f& get_view() const; const m4f& get_proj() const; }; +struct Camera_Id : public Primitive_Id { + using Primitive_Id::Primitive_Id; +}; + +template<> +struct Hash_Function { + size_t operator()(Camera_Id id) const { + return id.index; + } +}; + + #endif diff --git a/intermediate/surface.glsl b/intermediate/surface.glsl index 9fc1c48..10944ae 100644 --- a/intermediate/surface.glsl +++ b/intermediate/surface.glsl @@ -74,6 +74,15 @@ type: float [variable] name: colour type: vec3 +[variable] +name: caster_id +type: int + +[struct] +name: Caster +[variable] +name: projection +type: mat4 [cbuffer] name: c_vp @@ -95,6 +104,11 @@ name: lights type: Light stage: fragment +[sbuffer] +name: casters +type: Caster +stage: fragment + [texture] name: albedo stage: fragment @@ -119,6 +133,10 @@ dimension: 2 name: env_cube stage: fragment dimension: cube +[texture] +name: shadowmaps +stage: fragment +dimension: shadowArray [target] name: colour @@ -174,6 +192,51 @@ float specular_brdf(vec2 uv, vec3 ref, vec3 l, vec3 v, vec3 n) { return (D * F * G) / (4.0 * ndl * ndv + 0.001); } +vec2 poissonDisk[16] = vec2[]( + vec2(-0.94201624, -0.39906216), + vec2(0.94558609, -0.76890725), + vec2(-0.094184101, -0.92938870), + vec2(0.34495938, 0.29387760), + vec2(-0.91588581, 0.45771432), + vec2(-0.81544232, -0.87912464), + vec2(-0.38277543, 0.27676845), + vec2(0.97484398, 0.75648379), + vec2(0.44323325, -0.97511554), + vec2(0.53742981, -0.47373420), + vec2(-0.26496911, -0.41893023), + vec2(0.79197514, 0.19090188), + vec2(-0.24188840, 0.99706507), + vec2(-0.81409955, 0.91437590), + vec2(0.19984126, 0.78641367), + vec2(0.14383161, -0.14100790) +); + +float random(vec3 seed, int i){ + vec4 seed4 = vec4(seed,i); + float dot_product = dot(seed4, vec4(12.9898,78.233,45.164,94.673)); + return fract(sin(dot_product) * 43758.5453); +} + +float get_shadow(Light l, vec3 wpos) { + const int taps = 4; + const float w = 1.0 / float(taps); + const float m = 1.0 / 1000.0; + int i; + float d = 0.0f; + Caster caster = casters[l.caster_id]; + vec4 surf = caster.projection * vec4(wpos, 1.0); + surf /= surf.w; + surf.xy = surf.xy * 0.5 + 0.5; + surf.z -= 0.005; + for (i = 0; i < taps; i++) { + int index = int(16.0 * random(floor(wpos.xyz * 1000.0), i)) % 16; + vec2 coord = surf.xy + poissonDisk[index] * m; + vec4 vec = vec4(coord, float(l.caster_id), surf.z); + d += texture(shadowmaps, vec).r * w; + } + return d; +} + void main() { int i; vec2 uv = interpolator.uv; @@ -210,7 +273,10 @@ void main() { spec_col * specular_brdf(uv, ref, light_dir, view_dir, nrm) * cos_theta_i; - light += (diffuse + spec) * l.brightness * l.colour; + float shadow = 1.0f; + if (l.caster_id >= 0) + shadow = get_shadow(l, p); + light += (diffuse + spec) * l.brightness * l.colour * shadow; } colour = vec4(ambient + light, 1.0); diff --git a/lighting.cpp b/lighting.cpp index 75ae7c2..0e41ddd 100644 --- a/lighting.cpp +++ b/lighting.cpp @@ -1,5 +1,6 @@ #include "lighting.hpp" #include "model.hpp" +#include "renderer.hpp" #include "world.hpp" extern "C" { @@ -12,17 +13,28 @@ struct GPU_Light { v3f dir; float brightness; v3f colour; - float pad; + int caster_id; +}; + +struct GPU_Caster { + m4f projection; }; void Lighting::init(Device* dev) { int i; + Sampler_State ss{}; lights.init( dev, "Light buffer", max_lights * sizeof(GPU_Light), Buffer_Flags::storage_buffer ); + casters.init( + dev, + "Caster buffer", + max_shadows * sizeof(GPU_Caster), + Buffer_Flags::storage_buffer + ); shadows = dev->create_texture( "Shadowmap Array", texture_format_d16, @@ -35,6 +47,7 @@ void Lighting::init(Device* dev) { 0 ); for (i = 0; i < max_shadows; i++) { + cameras[i] = 0; shadow_slices[i] = dev->alias_texture( shadows, "Shadowmap Slice", @@ -49,18 +62,40 @@ void Lighting::init(Device* dev) { i ); } + ss.min = Filter_Mode::linear; + ss.mag = Filter_Mode::linear; + ss.mip = Filter_Mode::linear; + ss.address_u = Address_Mode::border; + ss.address_v = Address_Mode::border; + ss.border[0] = 1.0f; + ss.border[1] = 1.0f; + ss.border[2] = 1.0f; + ss.border[3] = 1.0f; + ss.compare = Depth_Mode::less; + shadow_sampler = dev->create_sampler("shadow sampler", ss); } -void Lighting::destroy(Device* dev) { +void Lighting::destroy(Device* dev, Renderer& r) { int i; lights.destroy(dev); - for (i = 0; i < max_shadows; i++) + casters.destroy(dev); + dev->destroy_sampler(shadow_sampler); + for (i = 0; i < max_shadows; i++) { dev->destroy_texture(shadow_slices[i]); + r.destroy_camera(cameras[i]); + } dev->destroy_texture(shadows); } -void Lighting::write_buf(void* ptr, World& w) { - GPU_Light* dst = (GPU_Light*)ptr; +void Lighting::write_bufs( + void* lptr, + void* cptr, + World& w, + Renderer& r, + Model_Scene& s +) { + GPU_Light* ldst = (GPU_Light*)lptr; + GPU_Caster* cdst = (GPU_Caster*)cptr; int count = 0, ccount = 0; for (auto v : w.view()) { GPU_Light gl; @@ -72,20 +107,37 @@ void Lighting::write_buf(void* ptr, World& w) { gl.brightness = l.brightness; gl.colour = l.colour; gl.dir = l.dir; - dst[count++] = gl; - if (l.caster) { - Caster& c = casters[ccount++]; - c.vp = m4f::identity(); - } + if (l.caster && ccount < max_shadows) { + int cid = ccount++; + GPU_Caster& c = cdst[cid]; + Camera_Id camid = cameras[cid]; + if (!camid) + camid = r.create_camera(); + Camera& cam = r.get_camera(camid); + cam.init_shadow(l.dir, s.bound.min, s.bound.max); + c.projection = cam.get_proj() * cam.get_view(); + cameras[cid] = camid; + gl.caster_id = cid; + } else + gl.caster_id = -1; + ldst[count++] = gl; } light_count = count; caster_count = ccount; } -void Lighting::update(Device* dev, Context& ctx, World& w) { +void Lighting::update( + Device* dev, + Context& ctx, + World& w, + Renderer& r, + Model_Scene& s +) { light_count = 0; - write_buf(lights.map(dev), w); + write_bufs(lights.map(dev), casters.map(dev), w, r, s); + casters.unmap(dev); lights.unmap(dev); lights.update(ctx); + casters.update(ctx); } diff --git a/lighting.hpp b/lighting.hpp index 627de66..ccd08d3 100644 --- a/lighting.hpp +++ b/lighting.hpp @@ -1,31 +1,43 @@ #ifndef lighting_hpp #define lighting_hpp +#include "camera.hpp" #include "maths.hpp" #include "video.hpp" struct Arena; struct Model_Resources; struct Model_Scene; +struct Renderer; struct World; -struct Caster { - m4f vp; -}; - struct Lighting { static constexpr int max_lights = 128; static constexpr int max_shadows = 16; - static constexpr int shadow_res = 512; + static constexpr int shadow_res = 2048; Staged_Buffer lights; + Staged_Buffer casters; Texture_Id shadows; Texture_Id shadow_slices[max_shadows]; - Caster casters[max_shadows]; + Sampler_Id shadow_sampler; + Camera_Id cameras[max_shadows]; int light_count, caster_count; void init(Device* dev); - void destroy(Device* dev); - void update(Device* dev, Context& ctx, World& w); - void write_buf(void* ptr, World& w); + void destroy(Device* dev, Renderer& r); + void update( + Device* dev, + Context& ctx, + World& w, + Renderer& r, + Model_Scene& s + ); + void write_bufs( + void* lptr, + void* cptr, + World& w, + Renderer& r, + Model_Scene& s + ); }; struct Light { diff --git a/maths.cpp b/maths.cpp index 39a1163..bdda15b 100644 --- a/maths.cpp +++ b/maths.cpp @@ -2,6 +2,15 @@ #include +void AABB::encompass(const AABB& other) { + min.x = std::min(min.x, other.min.x); + min.y = std::min(min.y, other.min.y); + min.z = std::min(min.z, other.min.z); + max.x = std::max(max.x, other.max.x); + max.y = std::max(max.y, other.max.y); + max.z = std::max(max.z, other.max.z); +} + namespace quat { v4f identity() { return v4f(0.0f, 0.0f, 0.0f, 1.0f); @@ -285,19 +294,12 @@ m4f m4f::pers(float fov, float asp, float n, float f) { m4f m4f::orth(float l, float r, float b, float t, float n, float f) { m4f res(1.0f); - float* data = (float*)res.m; - - float lr = 1.0f / (l - r); - float bt = 1.0f / (b - t); - float nf = 1.0f / (n - f); - - data[0] = -2.0f * lr; - data[5] = -2.0f * bt; - data[10] = 2.0f * nf; - - data[12] = (l + r) * lr; - data[13] = (t + b) * bt; - data[14] = (f + n) * nf; + res.m[0][0] = 2.0f / (r - l); + res.m[1][1] = 2.0f / (b - t); + res.m[2][2] = 1.0f / (n - f); + res.m[3][0] = -(l + r) / (r - l); + res.m[3][1] = -(b + t) / (b - t); + res.m[3][2] = n / (n - f); return res; } diff --git a/maths.hpp b/maths.hpp index e432529..eeedec1 100644 --- a/maths.hpp +++ b/maths.hpp @@ -474,6 +474,7 @@ template struct v4; struct AABB { v3f min, max; + void encompass(const AABB& other); }; namespace quat { diff --git a/model.cpp b/model.cpp index caa1422..765da15 100644 --- a/model.cpp +++ b/model.cpp @@ -136,6 +136,8 @@ Asset* Model_Loader::load( mesh.vp_binding_depth = depth_shader->descriptor_binding("c_vp"); mesh.mat_binding = shader->descriptor_binding("material"); mesh.light_binding = shader->descriptor_binding("lights"); + mesh.casters_binding = shader->descriptor_binding("casters"); + mesh.shadowmaps_binding = shader->descriptor_binding("shadowmaps"); mesh.env_cube_binding = shader->descriptor_binding("env_cube"); mesh.mesh_binding = shader->binding_index("mesh"); assert(mesh.model_binding >= 0); @@ -144,6 +146,8 @@ Asset* Model_Loader::load( assert(mesh.vp_binding_depth >= 0); assert(mesh.mat_binding >= 0); assert(mesh.light_binding >= 0); + assert(mesh.casters_binding >= 0); + assert(mesh.shadowmaps_binding >= 0); assert(mesh.mesh_binding >= 0); assert(mesh.env_cube_binding >= 0); pack_read(f, &vertex_size, 4); @@ -296,11 +300,15 @@ void Model_Instance::destroy(Device* dev, Heap* h) { void Model_Instance::update() { Mesh* meshes = m->get_meshes(); int i, c = m->mesh_count; - for (i = 0; i < c; i++) + bound.min = v3f( INFINITY); + bound.max = v3f(-INFINITY); + for (i = 0; i < c; i++) { bounds[i] = m4f::transform( transform * meshes[i].world, meshes[i].bound ); + bound.encompass(bounds[i]); + } } void Model_Instance::update_cbuffers( @@ -388,6 +396,8 @@ void Model_Instance::render( pb.depth(true, false, Depth_Mode::equal); pb.shader(mesh.shader); pb.sbuffer(mesh.light_binding, lighting->lights.gpuonly); + pb.sbuffer(mesh.casters_binding, lighting->casters.gpuonly); + pb.texture(mesh.shadowmaps_binding, lighting->shadows, lighting->shadow_sampler); mesh.material->use(pb, res.sampler, dev->get_shader(mesh.shader)); pb.cbuffer( mesh.mat_binding, @@ -413,6 +423,8 @@ void Model_Instance::render( } pb.cull(Cull_Mode::back); pb.vertex_format(shader.vf); + if (res.overrider) + res.overrider(pb); Pipeline& pip = pb.build(); ctx.submit(draw, pip, pass); } @@ -465,9 +477,12 @@ void Model_Scene::update( ) { int i; Model_Instance* instance = instances; + bound.min = v3f( INFINITY); + bound.max = v3f(-INFINITY); for (i = 0; i < count; i++, instance++) { instance->update(); instance->update_cbuffers(dev, lighting, cam); + bound.encompass(instance->bound); } } diff --git a/model.hpp b/model.hpp index 23f3825..e7b07e6 100644 --- a/model.hpp +++ b/model.hpp @@ -38,7 +38,9 @@ struct Mesh { vp_binding, vp_binding_depth, mat_binding, - light_binding; + light_binding, + shadowmaps_binding, + casters_binding; int env_cube_binding; bool world_dirty; m4f world, local; @@ -96,6 +98,7 @@ struct Model_Resources { Texture_Id env_cubemap; Sampler_Id sampler; Buffer_Id vp; + void (*overrider)(Pipeline_Builder&); }; struct Model_Instance { @@ -104,6 +107,7 @@ struct Model_Instance { m4f transform; Model* m; AABB* bounds; + AABB bound; void init(Device* dev, Heap* h, Model* model); void destroy(Device* dev, Heap* h); @@ -127,6 +131,7 @@ struct Model_Scene { Model_Instance* instances; int count, max; Sampler_Id sampler; + AABB bound; Model_Instance* instantiate(Device* dev, Model* model); void uninstantiate(Device* dev, Model_Instance* model); diff --git a/renderer.cpp b/renderer.cpp index 2d28ceb..cc7cc6d 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -57,11 +57,12 @@ void Drawlist::render( Device* dev, Arena* a, const Lighting* l, - Render_Pass& pass + Render_Pass& pass, + void (*overrider)(Pipeline_Builder&) ) { int i, c = count; const Camera& cam = r.get_camera(camera); - Model_Resources res; + Model_Resources res{}; VP_Cbuffer* vpc = (VP_Cbuffer*)vp.map(dev); vpc->view_projection = cam.get_proj() * cam.get_view(); vp.unmap(dev); @@ -69,6 +70,7 @@ void Drawlist::render( res.sampler = r.clamped_linear; res.env_cubemap = r.env_cubemap; res.vp = vp.gpuonly; + res.overrider = overrider; for (i = 0; i < c; i++) { models[i]->render(dev, a, pass, l, res); } @@ -102,7 +104,7 @@ void Renderer::render( } ctx.debug_push("depth prepass"); - drawlists[FORWARD].render(*this, dev, a, l, depth_prepass); + drawlists[FORWARD].render(*this, dev, a, l, depth_prepass, 0); ctx.debug_pop(); ctx.debug_push("shadow maps"); @@ -111,14 +113,18 @@ void Renderer::render( i < SHADOW_MAP_END && j < l->caster_count; i++, j++ ) { + auto o = [](Pipeline_Builder& pb) { + pb.cull(Cull_Mode::front); + }; + setcam(i, l->cameras[j]); ctx.debug_push("shadow map"); - drawlists[i].render(*this, dev, a, l, *shadow_passes[j]); + drawlists[i].render(*this, dev, a, l, *shadow_passes[j], o); ctx.debug_pop(); } ctx.debug_pop(); ctx.debug_push("forward"); - drawlists[FORWARD].render(*this, dev, a, l, forward_pass); + drawlists[FORWARD].render(*this, dev, a, l, forward_pass, 0); ctx.debug_pop(); } @@ -167,3 +173,8 @@ const Camera& Renderer::get_camera(Camera_Id id) const { void Renderer::destroy_camera(Camera_Id cam) { cameras.remove(cam); } + +void Renderer::setcam(int did, Camera_Id cam) { + assert(cam.index); + drawlists[did].camera = cam; +} diff --git a/renderer.hpp b/renderer.hpp index 29a9dd0..ae638e0 100644 --- a/renderer.hpp +++ b/renderer.hpp @@ -12,17 +12,6 @@ enum { SHADOW_MAP_END = SHADOW_MAP_START + Lighting::max_shadows, drawlist_count = SHADOW_MAP_END }; -struct Camera_Id : public Primitive_Id { - using Primitive_Id::Primitive_Id; -}; - -template<> -struct Hash_Function { - size_t operator()(Camera_Id id) const { - return id.index; - } -}; - struct Model_Instance; struct Renderer; @@ -38,7 +27,8 @@ struct Drawlist { Device* dev, Arena* a, const Lighting* l, - Render_Pass& pass + Render_Pass& pass, + void (*overrider)(Pipeline_Builder&) ); }; @@ -69,6 +59,7 @@ struct Renderer { Camera& get_camera(Camera_Id cam); const Camera& get_camera(Camera_Id cam) const; void destroy_camera(Camera_Id cam); + void setcam(int did, Camera_Id cam); }; #endif diff --git a/sc/sc.cpp b/sc/sc.cpp index d7e9038..d801a68 100644 --- a/sc/sc.cpp +++ b/sc/sc.cpp @@ -289,6 +289,8 @@ struct Desc { t.stage |= 1 << stage_from_string(sstage); t.dimension = sdem && string_equal(sdem, "cube")? -6: + sdem && string_equal(sdem, "array")? -20: + sdem && string_equal(sdem, "shadowArray")? -21: find_int_default(desc, "dimension", 2); } cfg_Object* read_struct(cfg_Object* desc) { @@ -495,6 +497,10 @@ struct Desc { ss << "uniform sampler"; if (texture.dimension == -6) ss << "Cube "; + else if (texture.dimension == -20) + ss << "2DArray "; + else if (texture.dimension == -21) + ss << "2DArrayShadow "; else ss << texture.dimension << "D "; ss << it.first << ";\n"; diff --git a/video.cpp b/video.cpp index 7fe26b1..fa98813 100644 --- a/video.cpp +++ b/video.cpp @@ -2346,6 +2346,22 @@ void Context::transition(Texture_Id id, Resource_State state) { b.dstAccessMask = 0; src_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dst_stage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + } else if ( + src_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL && + dst_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + ) { + b.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + b.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + src_stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dst_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } else if ( + src_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && + dst_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL + ) { + b.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + b.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + src_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dst_stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; } else if ( src_layout == VK_IMAGE_LAYOUT_UNDEFINED && dst_layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR @@ -2386,7 +2402,11 @@ void Context::transition(Texture_Id id, Resource_State state) { dst_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; } else { print_err("Bad resource transition.\n"); - pbreak(389); + assert(0); + b.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + b.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + src_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dst_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; } vkCmdPipelineBarrier( ctx->cb, @@ -4071,6 +4091,10 @@ void Sampler_Vk::init(Device_Vk* dev, const Sampler_State& s) { si.borderColor = VK_BORDER_COLOR_FLOAT_CUSTOM_EXT; si.maxLod = VK_LOD_CLAMP_NONE; si.pNext = &bi; + if ((int)s.compare) { + si.compareEnable = VK_TRUE; + si.compareOp = Pipeline_Vk::get_compare_op(s.compare); + } bi.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT; bi.customBorderColor = col; bi.format = VK_FORMAT_R32G32B32A32_SFLOAT; diff --git a/video.hpp b/video.hpp index 3bd756f..5aa25bc 100644 --- a/video.hpp +++ b/video.hpp @@ -75,13 +75,13 @@ static_assert(sizeof(Buffer_Descriptor) <= descriptor_payload_size); #define pipeline_max_descriptors 16 enum class Depth_Mode { + never, less, less_equal, equal, greater, greater_equal, - always, - never + always }; enum class Blend_Factor { @@ -410,6 +410,7 @@ struct Sampler_State { Address_Mode address_u; Address_Mode address_v; Address_Mode address_w; + Depth_Mode compare; float border[4]; float mip_bias; bool aniso; -- cgit v1.2.3-54-g00ecf