diff --git a/bin/data/config.json b/bin/data/config.json index 64d48ef8..950847d9 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -4,13 +4,13 @@ "start": "StartMenu", "matrix": { "reverseInfinite": true }, "meshes": { "interleaved": false }, - "lights": { "enabled": true, + "lights": { "enabled": false, "useLightmaps": false, - "max": 32, + "max": 16, "shadows": { - "enabled": true, - "update": 8, - "max": 32, + "enabled": false, + "update": 4, + "max": 16, "samples": 2 }, "bloom": { @@ -29,8 +29,8 @@ } }, "vxgi": { - // "limiter": 0, - "limiter": 0.0125, + "limiter": 0, + // "limiter": 0.0125, "size": 256, "dispatch": 16, "cascades": 3, @@ -117,7 +117,7 @@ "gui": true, "vsync": true, // vsync on vulkan side rather than engine-side "hdr": true, - "vxgi": true, + "vxgi": false, "culling": true, "bloom": true, "rt": false, @@ -355,7 +355,7 @@ "render modes": { "gui": true, "deferred": true }, "limiters": { "deltaTime": 5, - "framerate": 0 // "auto" // for some reason drops to 60 + "framerate": 120 // "auto" // for some reason drops to 60 }, "threads": { "workers" : "auto", diff --git a/bin/data/scenes/sourceengine/sourceengine.json b/bin/data/scenes/sourceengine/sourceengine.json index 95a20fe6..feac6dec 100644 --- a/bin/data/scenes/sourceengine/sourceengine.json +++ b/bin/data/scenes/sourceengine/sourceengine.json @@ -1,9 +1,9 @@ { // "import": "./rp_downtown_v2.json" -// "import": "./ss2_medsci1.json" + "import": "./ss2_medsci1.json" // "import": "./test_grid.json" // "import": "./sh2_mcdonalds.json" // "import": "./animal_crossing.json" - "import": "./mds_mcdonalds.json" +// "import": "./mds_mcdonalds.json" // "import": "./gm_construct.json" } \ No newline at end of file diff --git a/bin/data/shaders/display/depth-pyramid/comp.glsl b/bin/data/shaders/display/depth-pyramid/comp.glsl index 708815b9..efbaa5e5 100644 --- a/bin/data/shaders/display/depth-pyramid/comp.glsl +++ b/bin/data/shaders/display/depth-pyramid/comp.glsl @@ -16,15 +16,20 @@ layout( push_constant ) uniform PushBlock { uint pass; } PushConstant; -layout (binding = 3) uniform sampler2D inImage[MIPS]; -layout (binding = 4, r32f) uniform writeonly image2D outImage[MIPS]; +layout (binding = 0) uniform sampler2D samplerDepth; +layout (binding = 1) uniform sampler2D inImage[MIPS]; +layout (binding = 2, r32f) uniform writeonly image2D outImage[MIPS]; void main() { - vec2 imageSize = imageSize(outImage[PushConstant.pass]); - uvec2 pos = gl_GlobalInvocationID.xy; - if ( pos.x >= imageSize.x || pos.y >= imageSize.y ) return; + int mip = int(PushConstant.pass); - float depth = texture(inImage[PushConstant.pass], (vec2(pos) + vec2(0.5)) / imageSize).x; + float depth; + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + if ( mip == 0 ) { + depth = texelFetch(samplerDepth, pos, 0).r; + } else { + depth = texture(inImage[mip - 1], (vec2(gl_GlobalInvocationID.xy) + vec2(0.5)) / imageSize( outImage[mip] )).x; + } - imageStore(outImage[PushConstant.pass], ivec2(pos), vec4(depth)); + imageStore(outImage[mip], pos, vec4(depth)); } \ No newline at end of file diff --git a/bin/data/shaders/graph/cull/comp.glsl b/bin/data/shaders/graph/cull/comp.glsl index d941df4b..e0eb3301 100644 --- a/bin/data/shaders/graph/cull/comp.glsl +++ b/bin/data/shaders/graph/cull/comp.glsl @@ -51,8 +51,8 @@ bool projectSphere(vec3 C, float r, float znear, float P00, float P11, out vec4 } layout( push_constant ) uniform PushBlock { - uint pass; - uint passes; + uint pass; + uint passes; } PushConstant; layout (binding = 0) uniform Camera { @@ -73,10 +73,6 @@ layout (std140, binding = 3) buffer Objects { layout (binding = 4) uniform sampler2D samplerDepth; -struct Frustum { - vec4 planes[6]; -}; - vec4 normalizePlane( vec4 p ) { return p / length(p.xyz); } @@ -90,7 +86,7 @@ bool frustumCull( uint id ) { if ( drawCommand.indices == 0 || drawCommand.vertices == 0 ) return false; - bool visible = true; + bool visible = false; for ( uint pass = 0; pass < PushConstant.passes; ++pass ) { mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * object.model; vec4 planes[6]; { @@ -104,62 +100,69 @@ bool frustumCull( uint id ) { } } bool insideFrustum = true; - for ( uint p = 0; p < 6; ++p ) { - float d = max(instance.bounds.min.x * planes[p].x, instance.bounds.max.x * planes[p].x) - + max(instance.bounds.min.y * planes[p].y, instance.bounds.max.y * planes[p].y) - + max(instance.bounds.min.z * planes[p].z, instance.bounds.max.z * planes[p].z); - - if (d < -planes[p].w) { - visible = false; - break; - } - } - if ( !visible ) break; + for ( uint p = 0; p < 6; ++p ) { + float d = max(instance.bounds.min.x * planes[p].x, instance.bounds.max.x * planes[p].x) + + max(instance.bounds.min.y * planes[p].y, instance.bounds.max.y * planes[p].y) + + max(instance.bounds.min.z * planes[p].z, instance.bounds.max.z * planes[p].z); + + if (d < -planes[p].w) { + insideFrustum = false; + break; + } + } + + if ( insideFrustum ) { + visible = true; + break; + } } return visible; } bool occlusionCull( uint id ) { if ( PushConstant.passes == 0 ) return true; - + const DrawCommand drawCommand = drawCommands[id]; const Instance instance = instances[drawCommand.instanceID]; const Object object = objects[instance.objectID]; - bool visible = true; + bool visible = false; for ( uint pass = 0; pass < PushConstant.passes; ++pass ) { vec4 aabb; vec4 sphere = aabbToSphere( instance.bounds ); + + float scale = length(object.model[0].xyz); vec3 center = (camera.viewport[pass].view * object.model * vec4(sphere.xyz, 1)).xyz; - float radius = (object.model * vec4(sphere.w, 0, 0, 0)).x; + float radius = scale * sphere.w; mat4 proj = camera.viewport[pass].projection; float znear = proj[3][2]; float P00 = proj[0][0]; float P11 = proj[1][1]; - if (projectSphere(center, radius, znear, P00, P11, aabb)) { - ivec2 pyramidSize = textureSize( samplerDepth, 0 ); - float mips = mipLevels( pyramidSize ); + + if ( projectSphere( center, radius, znear, P00, P11, aabb ) ) { + vec2 pyramidSize = vec2(textureSize( samplerDepth, 0 )); float width = (aabb.z - aabb.x) * pyramidSize.x; float height = (aabb.w - aabb.y) * pyramidSize.y; - //find the mipmap level that will match the screen size of the sphere - float level = floor(log2(max(width, height))); - // if ( level == mips ) - --level; - level = clamp( level, 0, mips ); + float level = max(0.0, floor(log2(max(width, height)))); - //sample the depth pyramid at that specific level - float depth = textureLod(samplerDepth, (aabb.xy + aabb.zw) * 0.5, level).x; + float d1 = textureLod(samplerDepth, vec2(aabb.x, aabb.y), level).x; + float d2 = textureLod(samplerDepth, vec2(aabb.z, aabb.y), level).x; + float d3 = textureLod(samplerDepth, vec2(aabb.x, aabb.w), level).x; + float d4 = textureLod(samplerDepth, vec2(aabb.z, aabb.w), level).x; + float depth = min(min(d1, d2), min(d3, d4)); // min for reverse-z projection, max for standard float depthSphere = znear / (center.z - radius); - instances[drawCommand.instanceID].bounds.padding1 = depth; - instances[drawCommand.instanceID].bounds.padding2 = proj[3][2]; - - //if the depth of the sphere is in front of the depth pyramid value, then the object is visible - visible = visible && depthSphere >= depth - DEPTH_BIAS; + if ( depthSphere >= depth - DEPTH_BIAS ) { + visible = true; + break; + } + } else { + visible = true; + break; } } return visible; @@ -170,6 +173,6 @@ void main() { if ( !(0 <= gID && gID < drawCommands.length()) ) return; bool visible = frustumCull( gID ); -// if ( visible ) visible = occlusionCull( gID ); + if ( visible ) visible = occlusionCull( gID ); drawCommands[gID].instances = visible ? 1 : 0; } \ No newline at end of file diff --git a/engine/inc/uf/utils/math/physics/impl.h b/engine/inc/uf/utils/math/physics/impl.h index eb1a9a86..cddad46d 100644 --- a/engine/inc/uf/utils/math/physics/impl.h +++ b/engine/inc/uf/utils/math/physics/impl.h @@ -237,15 +237,15 @@ namespace pod { uint32_t reserveCount = 32; // amount of elements to reserve for vectors used in this system, to-do: have it tie to a memory pool allocator // increasing these make things lag for reasons I can imagine why - uint32_t broadphaseBvhCapacity = 4; // number of bodies per leaf node - uint32_t meshBvhCapacity = 4; // number of triangles per leaf node + uint32_t broadphaseBvhCapacity = 2; // number of bodies per leaf node + uint32_t meshBvhCapacity = 2; // number of triangles per leaf node // additionally flattens a BVH for linear iteration, rather than a recursive / stack-based traversal bool flattenBvhBodies = true; bool flattenBvhMeshes = true; // use surface area heuristics for building the BVH, rather than naive splits - bool useBvhSahBodies = true; // it actually seems slower to use these...... + bool useBvhSahBodies = true; bool useBvhSahMeshes = true; bool useSplitBvhs = true; // creates separate BVHs for static / dynamic objects diff --git a/engine/src/ext/vulkan/rendermodes/deferred.cpp b/engine/src/ext/vulkan/rendermodes/deferred.cpp index 2b9d47f4..d77a78d0 100644 --- a/engine/src/ext/vulkan/rendermodes/deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/deferred.cpp @@ -56,6 +56,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale); uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale); + uint32_t mips = uf::vector::mips( pod::Vector2ui{ width, height } ); renderTarget.device = &device; renderTarget.views = metadata.eyes; @@ -148,7 +149,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { /*.usage = */ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, /*.blend = */false, /*.samples = */1, - /*.mips = */1 + /*.mips = */mips, }); metadata.attachments["id"] = attachments.id; @@ -347,19 +348,18 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { shader.aliasAttachment("scratch", this, VK_IMAGE_LAYOUT_GENERAL); } - if ( false && settings::pipelines::culling ) { + if ( settings::pipelines::culling ) { uf::stl::string computeShaderFilename = uf::io::resolveURI(uf::io::root+"/shaders/display/depth-pyramid/comp.spv"); blitter.material.attachShader(computeShaderFilename, uf::renderer::enums::Shader::COMPUTE, "depth-pyramid"); auto& shader = blitter.material.getShader("compute", "depth-pyramid"); - auto attachment = this->getAttachment("depth"); auto mips = uf::vector::mips( pod::Vector2ui{ width, height } ); shader.setSpecializationConstants({ - { "MIPS", mips - 1 }, + { "MIPS", mips }, }); shader.setDescriptorCounts({ - { "inImage", mips - 1 }, - { "outImage", mips - 1 }, + { "inImage", mips }, + { "outImage", mips }, }); shader.aliasAttachment("depth", this); @@ -373,11 +373,11 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { VK_UNREGISTER_HANDLE(view); } ::depthPyramidViews.clear(); - ::depthPyramidViews.resize(mips-1); + ::depthPyramidViews.resize(mips); shader.textures.clear(); - for ( auto i = 1; i < mips; ++i ) { - auto& view = ::depthPyramidViews[i-1]; + for ( auto i = 0; i < mips; ++i ) { + auto& view = ::depthPyramidViews[i]; VkImageViewCreateInfo viewCreateInfo = {}; viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewCreateInfo.pNext = NULL; @@ -389,22 +389,23 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { viewCreateInfo.viewType = source.viewType; viewCreateInfo.format = source.format; viewCreateInfo.image = source.image; + VK_CHECK_RESULT(vkCreateImageView(device.logicalDevice, &viewCreateInfo, nullptr, &view)); VK_REGISTER_HANDLE(view); - - if ( i + 1 < mips ) { - auto& texture = shader.textures.emplace_back(); - texture.aliasTexture( source ); - texture.view = view; - texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - texture.updateDescriptors(); - } } - for ( auto i = 1; i < mips; ++i ) { - auto& view = ::depthPyramidViews[i-1]; + + for ( auto i = 0; i < mips; ++i ) { auto& texture = shader.textures.emplace_back(); texture.aliasTexture( source ); - texture.view = view; + texture.view = ::depthPyramidViews[i]; + texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + texture.updateDescriptors(); + } + + for ( auto i = 0; i < mips; ++i ) { + auto& texture = shader.textures.emplace_back(); + texture.aliasTexture( source ); + texture.view = ::depthPyramidViews[i]; texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL; texture.updateDescriptors(); } @@ -444,7 +445,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { } } - if ( false && settings::pipelines::culling ) { + if ( settings::pipelines::culling ) { descriptor.aux = uf::vector::mips( pod::Vector2ui{ width, height } ); descriptor.pipeline = "depth-pyramid"; descriptor.subpass = 0; @@ -473,18 +474,19 @@ void ext::vulkan::DeferredRenderMode::tick() { rebuild = true; renderTarget.initialize( *renderTarget.device ); - if ( false && settings::pipelines::culling ) { + if ( settings::pipelines::culling ) { auto& shader = blitter.material.getShader("compute", "depth-pyramid"); - auto attachment = this->getAttachment("depth"); auto mips = uf::vector::mips( pod::Vector2ui{ width, height } ); shader.setSpecializationConstants({ - { "MIPS", mips - 1 }, + { "MIPS", mips }, }); shader.setDescriptorCounts({ - { "inImage", mips - 1 }, - { "outImage", mips - 1 }, + { "inImage", mips }, + { "outImage", mips }, }); + shader.aliasAttachment("depth", this); + ext::vulkan::Texture2D source; source.aliasAttachment( this->getAttachment("depthPyramid") ); source.sampler.descriptor.reduction.enabled = true; source.sampler.descriptor.reduction.mode = VK_SAMPLER_REDUCTION_MODE_MIN; @@ -494,11 +496,11 @@ void ext::vulkan::DeferredRenderMode::tick() { VK_UNREGISTER_HANDLE(view); } ::depthPyramidViews.clear(); - ::depthPyramidViews.resize(mips-1); + ::depthPyramidViews.resize(mips); shader.textures.clear(); - for ( auto i = 1; i < mips; ++i ) { - auto& view = ::depthPyramidViews[i-1]; + for ( auto i = 0; i < mips; ++i ) { + auto& view = ::depthPyramidViews[i]; VkImageViewCreateInfo viewCreateInfo = {}; viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewCreateInfo.pNext = NULL; @@ -510,22 +512,24 @@ void ext::vulkan::DeferredRenderMode::tick() { viewCreateInfo.viewType = source.viewType; viewCreateInfo.format = source.format; viewCreateInfo.image = source.image; + VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewCreateInfo, nullptr, &view)); VK_REGISTER_HANDLE(view); - - if ( i + 1 < mips ) { - auto& texture = shader.textures.emplace_back(); - texture.aliasTexture( source ); - texture.view = view; - texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - texture.updateDescriptors(); - } + } - for ( auto i = 1; i < mips; ++i ) { - auto& view = ::depthPyramidViews[i-1]; + + for ( auto i = 0; i < mips; ++i ) { auto& texture = shader.textures.emplace_back(); texture.aliasTexture( source ); - texture.view = view; + texture.view = ::depthPyramidViews[i]; + texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + texture.updateDescriptors(); + } + + for ( auto i = 0; i < mips; ++i ) { + auto& texture = shader.textures.emplace_back(); + texture.aliasTexture( source ); + texture.view = ::depthPyramidViews[i]; texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL; texture.updateDescriptors(); } @@ -588,7 +592,7 @@ void ext::vulkan::DeferredRenderMode::tick() { } } - if ( false && settings::pipelines::culling ) { + if ( settings::pipelines::culling ) { descriptor.aux = uf::vector::mips( pod::Vector2ui{ width, height } ); descriptor.pipeline = "depth-pyramid"; descriptor.subpass = 0; @@ -896,55 +900,39 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto } // construct depth-pyramid - #if 0 + #if 1 if ( settings::pipelines::culling && blitter.material.hasShader("compute", "depth-pyramid") ) { auto& shader = blitter.material.getShader("compute", "depth-pyramid"); - // auto mips = attachment.descriptor.mips; // uf::vector::mips( pod::Vector2ui{ renderTarget.width, renderTarget.height } ); auto mips = uf::vector::mips( pod::Vector2ui{ width, height } ); ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor; descriptor.renderMode = ""; - descriptor.aux = uf::vector::mips( pod::Vector2ui{ width, height } ); + descriptor.aux = mips; descriptor.pipeline = "depth-pyramid"; - descriptor.bind.width = width; - descriptor.bind.height = height; descriptor.bind.depth = metadata.eyes; descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE; descriptor.subpass = 0; - /* - // transition attachments to general attachments for imageStore - VkImageSubresourceRange subresourceRange; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = 1; - subresourceRange.baseArrayLayer = 0; - subresourceRange.layerCount = mips; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - subresourceRange.layerCount = this->metadata.eyes; - - auto& attachment = this->getAttachment("depth"); - uf::renderer::Texture::setImageLayout( commandBuffer, attachment.image, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, subresourceRange ); - */ - // dispatch compute shader VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER}; memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - for ( auto i = 0; i < mips - 1; ++i ) { - descriptor.bind.width = width >> i; - descriptor.bind.height = height >> i; - if ( descriptor.bind.width < 1 ) descriptor.bind.width = 1; - if ( descriptor.bind.height < 1 ) descriptor.bind.height = 1; + device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "setImageLayout" ); + ::transitionAttachmentsTo( this, shader, commandBuffer ); + + for ( auto i = 0; i < mips; ++i ) { + // for some reason it dispatches at half the width without offsetting back... + descriptor.bind.width = std::max(1u, width >> (i - 1)); + descriptor.bind.height = std::max(1u, height >> (i - 1)); + + blitter.record(commandBuffer, descriptor, 0, i); - blitter.record(commandBuffer, descriptor, 0, i, frame); vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 1, &memoryBarrier, 0, NULL, 0, NULL ); } - /* - // transition attachments to general attachments for imageStore - uf::renderer::Texture::setImageLayout( commandBuffer, attachment.image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, subresourceRange ); - */ + device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "setImageLayout" ); + ::transitionAttachmentsFrom( this, shader, commandBuffer ); } #endif // post-renderpass commands @@ -968,7 +956,6 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto uf::renderer::Texture::setImageLayout( commandBuffer, attachment.image, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageMemoryBarrier.subresourceRange ); #endif - for ( size_t eye = 0; eye < metadata.eyes; ++eye ) { texture.generateMipmaps(commandBuffer, eye); }