#include "pch.h" #include "DeferredPass.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "DeferredPass.h" #if 1 namespace idk::vkn { using EGBufferBinding = meta::enum_info>; enum class DeferredBinding { eMetallicPass , eSpecularPass , eUnlitPass , eDepths }; using EDeferredBinding = meta::enum_info>; struct DeferredBindingIndex { static constexpr uint32_t fb_buffer_size [EDeferredBinding::size()] = { static_cast(EDeferredBinding::size()),static_cast(EDeferredBinding::size()),1,3}; static constexpr uint32_t begin(DeferredBinding binding) { uint32_t result = 0; for (int i = 0; i < (int)binding; ++i) { result += fb_buffer_size[i]; } return result; } static constexpr uint32_t end (DeferredBinding binding) { uint32_t result = 0; for (int i = 0; i <= (int)binding; ++i) { result += fb_buffer_size[i]; } return result; } static constexpr uint32_t size(DeferredBinding binding) { return fb_buffer_size[(int)binding] ; } }; pipeline_config ConfigWithVP(pipeline_config config, const CameraData& camera, const ivec2& offset, const uvec2& size); template using has_setstate = decltype(std::declval().SetState(std::declval()...)); PipelineThingy ProcessRoUniforms(const GraphicsState& state, UboManager& ubo_manager, StandardBindings& binders); std::pair ComputeVulkanViewport(const vec2& sz, const rect& vp); void GBufferBarrier(vk::CommandBuffer cmd_buffer, DeferredGBuffer& gbuffer) { constexpr auto num_buffers = 0;// EGBufferBinding::size(); std::array barriers; //for (size_t i = 0; i < EGBufferBinding::size(); ++i) //{ // auto& tex = gbuffer.gbuffer->GetAttachment(i).buffer.as(); // barriers[i] = vk::ImageMemoryBarrier // { // vk::AccessFlagBits::eColorAttachmentWrite, // vk::AccessFlagBits::eShaderRead, // vk::ImageLayout::eColorAttachmentOptimal, // vk::ImageLayout::eShaderReadOnlyOptimal, // *View().QueueFamily().graphics_family, // *View().QueueFamily().graphics_family, // tex.Image(), // vk::ImageSubresourceRange // { // tex.ImageAspects(), // 0,1, // 0,1, // } // }; //} auto& depth_tex = gbuffer.gbuffer->DepthAttachment().buffer.as(); //depth barriers[num_buffers] = vk::ImageMemoryBarrier { {}, vk::AccessFlagBits::eTransferRead, vk::ImageLayout::eGeneral, vk::ImageLayout::eTransferSrcOptimal, *View().QueueFamily().graphics_family, *View().QueueFamily().graphics_family, depth_tex.Image(), vk::ImageSubresourceRange { depth_tex.ImageAspects(), 0,1, 0,1, } }; cmd_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion, nullptr, nullptr, barriers, vk::DispatchLoaderDefault{}); } vk::Semaphore DeferredGBuffer::RenderCompleteSignal() { return *_render_complete; } struct RpBindInfo { index_t index; }; struct SubFramebuffer { vector color_attachments; index_t depth_attachment; }; bool DeferredGBuffer::Init(uvec2 size) { bool inited = false; if (!gbuffer || gbuffer->Size()!=size) { inited = true; FrameBufferBuilder fbf; fbf.Begin("GBuffer",size) .AddAttachment(idk::AttachmentInfo{ // GBufferBinding::eAlbedoAmbOcc LoadOp::eClear,StoreOp::eStore, TextureInternalFormat::RGBA_8, FilterMode::_enum::Nearest }) .AddAttachment(idk::AttachmentInfo{ // GBufferBinding::eUvMetallicRoughness LoadOp::eClear,StoreOp::eStore, TextureInternalFormat::RGBA_8, FilterMode::_enum::Nearest }) .AddAttachment(idk::AttachmentInfo{ // GBufferBinding::eViewPos LoadOp::eClear,StoreOp::eStore, TextureInternalFormat::RGBA_16_F, FilterMode::_enum::Nearest }) .AddAttachment(idk::AttachmentInfo{ // GBufferBinding::eNormal LoadOp::eClear,StoreOp::eStore, TextureInternalFormat::RGBA_8, FilterMode::_enum::Nearest }) .AddAttachment(idk::AttachmentInfo{ // GBufferBinding::eTangent LoadOp::eClear,StoreOp::eStore, TextureInternalFormat::RGBA_8, FilterMode::_enum::Nearest }) .SetDepthAttachment(idk::AttachmentInfo{ LoadOp::eClear,StoreOp::eStore, TextureInternalFormat::DEPTH_32_F_STENCIL_8, FilterMode::_enum::Nearest }); auto fb_info = fbf.End(); auto& fb_factory = Core::GetResourceManager().GetFactory(); if (gbuffer) Core::GetResourceManager().Release(gbuffer); auto new_buffer = fb_factory.Create(fb_info); gbuffer = RscHandle{ new_buffer }; fbf.Begin("Accum Buffer",size); fbf.AddAttachment(idk::AttachmentInfo{ LoadOp::eClear,StoreOp::eStore, TextureInternalFormat::RGBA_16_F, FilterMode::_enum::Nearest }); uint32_t i = 0; for (i = 0; i < EGBufferBinding::size(); ++i) { auto att = idk::AttachmentInfo{ LoadOp::eLoad,StoreOp::eDontCare, TextureInternalFormat::RGBA_16_F, FilterMode::_enum::Nearest, false, gbuffer->GetAttachment(i).buffer }; att.is_input_att = true; fbf.AddAttachment(att); } auto vkn_att = idk::AttachmentInfo{ LoadOp::eLoad,StoreOp::eDontCare, TextureInternalFormat::DEPTH_32_F, FilterMode::_enum::Nearest, false, gbuffer->DepthAttachment().buffer }; vkn_att.override_as_depth = true; vkn_att.is_input_att = true; fbf.AddAttachment(vkn_att); if (accum_buffer) Core::GetResourceManager().Release(accum_buffer); accum_buffer = RscHandle{ fb_factory.Create(fbf.End()) }; _render_complete = View().Device()->createSemaphoreUnique(vk::SemaphoreCreateInfo{}); } return inited; } //// vk::UniqueRenderPass BuildAccumRenderPass(VknFrameBuffer& fb) { RenderPassInfo rp_info; SubPassConfig spc{}; //Output spc.AddOutputAttachment(0, vk::ImageLayout::eColorAttachmentOptimal); rp_info.RegisterAttachment(fb.GetAttachment(0), vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal); uint32_t i = 0; for (i = 0; i < EGBufferBinding::size(); ++i) { spc.AddInputAttachment(1+i, vk::ImageLayout::eShaderReadOnlyOptimal); rp_info.RegisterAttachment(fb.GetAttachment(1 + i), vk::ImageLayout::eGeneral, vk::ImageLayout::eShaderReadOnlyOptimal); } spc.AddInputAttachment(1+i, vk::ImageLayout::eShaderReadOnlyOptimal); rp_info.RegisterAttachment(fb.GetAttachment(1 + i), vk::ImageLayout::eGeneral, vk::ImageLayout::eShaderReadOnlyOptimal); spc.BuildSubpass(); rp_info.RegisterSubpass(spc); rp_info.AddDependency(VK_SUBPASS_EXTERNAL, 0, {},vk::AccessFlagBits::eColorAttachmentRead, vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eFragmentShader ); auto tmp = rp_info.BuildRenderPass(); return View().Device()->createRenderPassUnique(tmp); } //// vk::UniqueRenderPass BuildHdrRenderPass(const FrameBufferInfo& hdr_out) { RenderPassInfo rp_info; //Output int i = 0; SubPassConfig spc{}; spc.AddOutputAttachment(i, vk::ImageLayout::eColorAttachmentOptimal); rp_info.RegisterAttachment(hdr_out.attachments[i++], vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral); spc.AddInputAttachment(i, vk::ImageLayout::eShaderReadOnlyOptimal); rp_info.RegisterAttachment(hdr_out.attachments[i++], vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); spc.AddInputAttachment(i, vk::ImageLayout::eShaderReadOnlyOptimal); rp_info.RegisterAttachment(hdr_out.attachments[i++], vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); spc.AddInputAttachment(i, vk::ImageLayout::eShaderReadOnlyOptimal); rp_info.RegisterAttachment(hdr_out.attachments[i++], vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); spc.AddInputAttachment(i, vk::ImageLayout::eShaderReadOnlyOptimal); rp_info.RegisterAttachment(hdr_out.attachments[i++], vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); spc.SetDepthAttachment(i, vk::ImageLayout::eDepthStencilAttachmentOptimal); rp_info.RegisterAttachment(*hdr_out.depth_attachment, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral); spc.BuildSubpass(); rp_info.RegisterSubpass(spc); rp_info.AddDependency(VK_SUBPASS_EXTERNAL, 0, vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite, vk::AccessFlagBits::eShaderRead, vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eLateFragmentTests, vk::PipelineStageFlagBits::eFragmentShader); //auto create_info = rp_info.BuildRenderPass(); return View().Device()->createRenderPassUnique(rp_info.BuildRenderPass()); } void DeferredPass::Init(VknRenderTarget& ) { } void DeferredPass::Init(VknRenderTarget& rt, DeferredGBuffer(&gbuf)[EGBufferType::size()]) { _gbuffer = &gbuf; const static renderer_attributes fsq_requirements = { { {vtx::Attrib::Position,0}, {vtx::Attrib::UV,1}, } }; { if (!hdr_frag) { auto frag_opt = Core::GetResourceManager().Load("/engine_data/shaders/deferred_hdr.frag", false); if (frag_opt) hdr_frag = *frag_opt; } } if (!hdr_buffer ||(hdr_buffer->Size() != rt.Size() || hdr_buffer->attachments[0]->buffer!=rt.GetColorBuffer())) { auto& fb_factory = Core::GetResourceManager().GetFactory(); FrameBufferBuilder fbf; fbf.Begin("HDR Buffer",rt.Size()); auto ai = idk::AttachmentInfo{ LoadOp::eLoad,StoreOp::eStore, TextureInternalFormat::SRGBA_8, FilterMode::_enum::Nearest,false, rt.GetColorBuffer() }; fbf.AddAttachment(ai); auto add_src = [](FrameBufferBuilder& fbf, auto& gbuffer) { auto& buffer = *gbuffer.accum_buffer; auto accum_att = idk::AttachmentInfo{ LoadOp::eLoad,StoreOp::eDontCare, TextureInternalFormat::SRGB_8, FilterMode::_enum::Nearest,false, buffer.GetAttachment(0).buffer }; accum_att.is_input_att = true; fbf.AddAttachment(accum_att); auto depth_att = idk::AttachmentInfo{ LoadOp::eLoad,StoreOp::eDontCare, TextureInternalFormat::DEPTH_32_F_STENCIL_8, FilterMode::_enum::Nearest,false, gbuffer.gbuffer->DepthAttachment().buffer }; depth_att.override_as_depth = true; depth_att.is_input_att = true; fbf.AddAttachment(depth_att); }; for (auto& gbuffer : GBuffers()) add_src(fbf, gbuffer); auto depth_att = idk::AttachmentInfo{ LoadOp::eDontCare,StoreOp::eStore, TextureInternalFormat::DEPTH_32_F_STENCIL_8, FilterMode::_enum::Nearest,false, rt.GetDepthBuffer()//GetColorBuffer() }; fbf.SetDepthAttachment(depth_att); if (hdr_buffer) Core::GetResourceManager().Release(hdr_buffer); auto hdr_info = fbf.End(); hdr_pass = RenderPassObj{ BuildHdrRenderPass(hdr_info) }; auto tmp = VknSpecializedInfo{ hdr_pass }; hdr_buffer = RscHandle{ fb_factory.Create(hdr_info,&tmp) }; } if(!accum_pass) accum_pass = BuildAccumRenderPass(GBuffers()[0].accum_buffer.as()); if(!hdr_pass) hdr_pass = hdr_buffer->GetRenderPass(); fsq_light_ro.mesh = fsq_amb_ro.mesh = Mesh::defaults[MeshType::INV_FSQ]; fsq_light_ro.renderer_req = fsq_amb_ro.renderer_req = &fsq_requirements; if (!fsq_light_ro.config) { ambient_config = std::make_shared(*Core::GetSystem().MeshRenderConfig()); light_config = std::make_shared(*Core::GetSystem().MeshRenderConfig()); light_config->attachment_configs.resize(1); auto& blend = light_config->attachment_configs[0]; blend.blend_enable = true; blend.dst_color_blend_factor = BlendFactor::eOne; blend.src_color_blend_factor = BlendFactor::eOne; blend.color_blend_op = BlendOp::eAdd; blend.alpha_blend_op = BlendOp::eMax; blend.dst_alpha_blend_factor = BlendFactor::eOne; blend.src_alpha_blend_factor = BlendFactor::eOne; light_config->depth_test = false; fsq_light_ro.config = light_config; fsq_amb_ro.config = ambient_config; } } GBufferType MapToGBufferType(ShadingModel model)noexcept { switch (model) { case ShadingModel::_enum::Specular: return GBufferType::eSpecular; break; case ShadingModel::_enum::DefaultLit: return GBufferType::eMetallic; break; default: LOG_TO(LogPool::GFX, "GBufferType doesn't support %s yet. Defaulting to eMetallic", model.to_string().data()); return GBufferType::eMetallic; break; } } static auto& PopulateGbufferNames() { static const char* gbuffer_names[EGBufferBinding::size()+1]; gbuffer_names[EGBufferBinding::map(GBufferBinding::eAlbedoAmbOcc)] = "gAlbAmbOcc"; gbuffer_names[EGBufferBinding::map(GBufferBinding::eViewPos)] = "gViewPos"; gbuffer_names[EGBufferBinding::map(GBufferBinding::eNormal)] = "gNormal"; gbuffer_names[EGBufferBinding::map(GBufferBinding::eTangent)] = "gTangent"; gbuffer_names[EGBufferBinding::map(GBufferBinding::eUvMetallicRoughness)] = "gUvMetRough"; gbuffer_names[EGBufferBinding::size()] = "gDepth"; return gbuffer_names; } static const auto gbuffer_names = PopulateGbufferNames(); struct DeferredPostBinder : StandardBindings { bool is_ambient = false; GBufferType type; DeferredPass* deferred_pass; void SetDeferredPass(DeferredPass& pass) { deferred_pass = &pass; } bool Skip(PipelineThingy&, const RenderObject& dc) { return MapToGBufferType(dc.material_instance->material->model) != type; } void Bind(PipelineThingy& the_interface) override { RscHandle fsq_vert = deferred_pass->fullscreen_quad_vert; RscHandle deferred_post_frag = deferred_pass->deferred_post_frag[EGBufferType::map(type)]; RscHandle deferred_post_ambient = deferred_pass->deferred_post_ambient; the_interface.BindShader(ShaderStage::Vertex, fsq_vert); the_interface.BindShader(ShaderStage::Fragment, (is_ambient)? deferred_post_ambient:deferred_post_frag); auto& gbuffer_fb = deferred_pass->GBuffer(type).gbuffer; for (uint32_t i = 0; i < EGBufferBinding::size(); ++i) the_interface.BindAttachment(gbuffer_names[i], 0, gbuffer_fb->GetAttachment(i).buffer.as(),true,vk::ImageLayout::eShaderReadOnlyOptimal); the_interface.BindAttachment(gbuffer_names[static_cast(EGBufferBinding::size())], 0, gbuffer_fb->DepthAttachment().buffer.as(),false, vk::ImageLayout::eShaderReadOnlyOptimal); } }; struct DeferredHdrBinder : StandardBindings { bool is_ambient = false; DeferredPass* deferred_pass; void SetDeferredPass(DeferredPass& pass) { deferred_pass = &pass; } void Bind(PipelineThingy& the_interface) override { RscHandle fsq_vert = deferred_pass->fullscreen_quad_vert; RscHandle hdr_frag = deferred_pass->hdr_frag; the_interface.BindShader(ShaderStage::Vertex, fsq_vert); the_interface.BindShader(ShaderStage::Fragment, hdr_frag); } }; using PbrDeferredPostBinding = CombinedBindings; void DeferredPass::LightPass(GBufferType type, PipelineThingy& the_interface, const GraphicsState& graphics_state, [[maybe_unused]]RenderStateV2& rs, std::optional> light_range,bool is_ambient) { PbrDeferredPostBinding binding; auto& def_bind = std::get(binding.binders); def_bind.type = type; def_bind.SetDeferredPass(*this); def_bind.is_ambient = is_ambient; auto& pbr_fwd_binding = std::get(binding.binders); pbr_fwd_binding.light_range = light_range; pbr_fwd_binding.rebind_light = true; pbr_fwd_binding.SetState(graphics_state); auto& fsq_ro = (is_ambient) ? fsq_amb_ro : fsq_light_ro; binding.Bind(the_interface); binding.Bind(the_interface, fsq_ro); the_interface.BindMeshBuffers(fsq_ro); //Draw Fullscreen Quad the_interface.FinalizeDrawCall(fsq_ro); //Insert Forward stuff here? } static std::pair hdr_attachment_info[] = { {"metallic_light_accum_input" , vk::ImageLayout::eShaderReadOnlyOptimal}, {"metallic_depth_input" , vk::ImageLayout::eShaderReadOnlyOptimal }, {"specular_light_accum_input" , vk::ImageLayout::eShaderReadOnlyOptimal}, {"specular_depth_input" , vk::ImageLayout::eShaderReadOnlyOptimal }, }; PipelineThingy DeferredPass::HdrPass([[maybe_unused]]const GraphicsState& graphics_state, RenderStateV2& rs) { PipelineThingy the_interface{}; the_interface.SetRef(rs.ubo_manager); DeferredHdrBinder binding; binding.SetDeferredPass(*this); auto& fsq_ro = fsq_amb_ro ; binding.Bind(the_interface); auto& buffer = *hdr_buffer; /*for (auto& g_buffer : GBuffers()) { auto& gbuffer = g_buffer.gbuffer.as(); }*/ int i = 1; for (auto& [name, layout]:hdr_attachment_info ) the_interface.BindAttachment(name, 0, buffer.GetAttachment(i++).buffer.as(), false, layout); the_interface.BindMeshBuffers(fsq_ro); //Draw Fullscreen Quad the_interface.FinalizeDrawCall(fsq_ro); return the_interface; } void PostRenderCopy(vk::CommandBuffer cmd_buffer,ivec2 size, vk::Image render_target_depth, vk::Image gbuffer_depth) { //Transit RTD -> Transfer vk::ImageMemoryBarrier depth { {}, vk::AccessFlagBits::eTransferWrite, vk::ImageLayout::eDepthStencilAttachmentOptimal, vk::ImageLayout::eTransferDstOptimal, *View().QueueFamily().graphics_family, *View().QueueFamily().graphics_family, render_target_depth, vk::ImageSubresourceRange { vk::ImageAspectFlagBits::eDepth, 0,1,0,1 } }; std::array convert_barriers = { depth,depth }; convert_barriers[1].setDstAccessMask(vk::AccessFlagBits::eTransferRead); convert_barriers[1].setOldLayout(vk::ImageLayout::eShaderReadOnlyOptimal); convert_barriers[1].setNewLayout(vk::ImageLayout::eTransferSrcOptimal); convert_barriers[1].setImage(gbuffer_depth); cmd_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eBottomOfPipe, vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion, nullptr, nullptr, convert_barriers); //Blit //expect depth attachments to be the exact same size and format. cmd_buffer.copyImage( gbuffer_depth, vk::ImageLayout::eTransferSrcOptimal, render_target_depth, vk::ImageLayout::eTransferDstOptimal, vk::ImageCopy { vk::ImageSubresourceLayers { vk::ImageAspectFlagBits::eDepth, 0u,0u,1u }, vk::Offset3D{0,0,0}, vk::ImageSubresourceLayers { vk::ImageAspectFlagBits::eDepth, 0ui32,0ui32,1ui32 }, vk::Offset3D{0,0,0}, vk::Extent3D{s_cast(size.x),s_cast(size.y)} } ); //Transit RTD -> General std::array & return_barriers = convert_barriers;// { depth, depth }; std::swap(return_barriers[0].dstAccessMask, return_barriers[0].srcAccessMask); std::swap(return_barriers[0].oldLayout, return_barriers[0].newLayout); return_barriers[0].setDstAccessMask({});// vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite); return_barriers[0].setNewLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal); //Transit GD -> DepthAttachmentOptimal return_barriers[1].setSrcAccessMask(vk::AccessFlagBits::eTransferRead); return_barriers[1].setDstAccessMask({}); return_barriers[1].setOldLayout(vk::ImageLayout::eTransferSrcOptimal); return_barriers[1].setNewLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal); return_barriers[1].setImage(gbuffer_depth); cmd_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eEarlyFragmentTests, vk::DependencyFlagBits::eByRegion, nullptr, nullptr, return_barriers); } bool RenderProcessedDrawCalls(vk::CommandBuffer cmd_buffer, const vector& processed_ro, const CameraData& camera, PipelineManager& pipeline_manager, uint32_t frame_index, const vk::RenderPassBeginInfo& rpbi, RenderPassObj render_pass, uint32_t num_attachments, const GraphicsState* state = nullptr ) { auto offset = ivec2{ rpbi.renderArea.offset.x,rpbi.renderArea.offset.y }; auto size= uvec2{ s_cast(rpbi.renderArea.extent.width),s_cast(rpbi.renderArea.extent.height )}; auto& view = View(); vector> shaders; VulkanPipeline* prev_pipeline = nullptr; //Draw stuff into the gbuffers //auto& processed_ro = the_interface.DrawCalls(); bool rendered = false; for (auto& p_ro : processed_ro) { rendered = true; auto& obj = p_ro.Object(); bool is_mesh_renderer = p_ro.vertex_shader == Core::GetSystem().renderer_vertex_shaders[VNormalMesh]; if (p_ro.rebind_shaders) { shaders.resize(0); if (p_ro.frag_shader) shaders.emplace_back(*p_ro.frag_shader); if (p_ro.vertex_shader) shaders.emplace_back(*p_ro.vertex_shader); if (p_ro.geom_shader) shaders.emplace_back(*p_ro.geom_shader); auto config = ConfigWithVP(*obj.config, camera, offset, size); config.attachment_configs.resize(num_attachments); if (is_mesh_renderer) config.buffer_descriptions.emplace_back( buffer_desc { buffer_desc::binding_info{ std::nullopt,sizeof(mat4) * 2,VertexRate::eInstance}, {buffer_desc::attribute_info{AttribFormat::eMat4,4,0,true}, buffer_desc::attribute_info{AttribFormat::eMat4,8,sizeof(mat4),true} } } ); auto& pipeline = pipeline_manager.GetPipeline(config, shaders, frame_index, render_pass, true); pipeline.Bind(cmd_buffer, view); SetViewport(cmd_buffer, offset, size); prev_pipeline = &pipeline; } auto& pipeline = *prev_pipeline; auto& mesh = obj.mesh.as(); { uint32_t set = 0; for (auto& ods : p_ro.descriptor_sets) { if (ods) { auto& ds = *ods; cmd_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, *pipeline.pipelinelayout, set, ds, {}); } ++set; } } auto& renderer_req = *obj.renderer_req; for (auto&& [attrib, location] : renderer_req.mesh_requirements) { auto& attrib_buffer = mesh.Get(attrib); cmd_buffer.bindVertexBuffers(*pipeline.GetBinding(location), *attrib_buffer.buffer(), vk::DeviceSize{ attrib_buffer.offset }, vk::DispatchLoaderDefault{}); } if (state&&is_mesh_renderer) { uint32_t obj_trf_loc = 4; cmd_buffer.bindVertexBuffers(*pipeline.GetBinding(obj_trf_loc), state->shared_gfx_state->inst_mesh_render_buffer.buffer(), { 0 }, vk::DispatchLoaderDefault{}); } auto& oidx = mesh.GetIndexBuffer(); if (oidx) { cmd_buffer.bindIndexBuffer(*(*oidx).buffer(), 0, mesh.IndexType(), vk::DispatchLoaderDefault{}); cmd_buffer.drawIndexed(mesh.IndexCount(), static_cast(p_ro.num_instances), 0, 0, static_cast(p_ro.inst_offset), vk::DispatchLoaderDefault{}); } } return rendered; } struct TypeCheck : StandardBindings { ShadingModel model; bool Skip([[maybe_unused]]PipelineThingy& the_interface, const RenderObject& dc) override { if (dc.material_instance) { auto& mat_inst = *dc.material_instance; if (mat_inst.material) { auto& mat = *mat_inst.material; return mat.blend != BlendMode::Opaque || mat.model != model; } } return true; } }; using PbrDeferredGbufferBinding = CombinedBindings; static ShadingModel gbuffer_type_to_model[] = {ShadingModel::DefaultLit,ShadingModel::Specular}; void DeferredPass::DrawToGBuffers(vk::CommandBuffer cmd_buffer,const GraphicsState& graphics_state,RenderStateV2& rs) { int i = 0; std::array depth_clear{ 1.0f,1.0f ,1.0f ,1.0f }; std::array g_clear{ 0.0f,0.0f ,0.0f ,0.0f }; auto& camera = graphics_state.camera; const rect& viewport = graphics_state.camera.viewport; for (auto& gbuffer : GBuffers()) { //Bind the material uniforms PbrDeferredGbufferBinding binder; binder.for_each_binder([](auto& binder, const GraphicsState& state) { binder.SetState(state); }, graphics_state); auto& type_checker = std::get(binder.binders); type_checker.model = gbuffer_type_to_model[i]; //Preprocess MeshRender's uniforms auto&& the_interface = ProcessRoUniforms(graphics_state, rs.ubo_manager, binder); the_interface.GenerateDS(rs.dpools,false); //std::array a{}; auto& g_buffer = *gbuffer.gbuffer; auto frame_buffer = g_buffer.GetFramebuffer(); //auto sz = ; auto [offset, size] = ComputeVulkanViewport(vec2{ g_buffer.Size() }, viewport); vk::ClearValue v[EGBufferBinding::size()+1]{}; for(auto& value : v) { value = vk::ClearValue{ g_clear }; }; v[EGBufferBinding::size()] =vk::ClearValue{ vk::ClearColorValue{ depth_clear } }; vk::Rect2D render_area { vk::Offset2D { s_cast(offset.x),s_cast(offset.y) },vk::Extent2D { s_cast(size.x),s_cast(size.y) } }; auto& rp = g_buffer.GetRenderPass(); vk::RenderPassBeginInfo rpbi { *rp, frame_buffer, render_area,hlp::arr_count(v),std::data(v) }; cmd_buffer.beginRenderPass(rpbi, vk::SubpassContents::eInline); if (RenderProcessedDrawCalls(cmd_buffer, the_interface.DrawCalls(), camera, pipeline_manager(), frame_index(), rpbi,rp,static_cast(g_buffer.NumColorAttachments()),&graphics_state)) rs.FlagRendered(); cmd_buffer.endRenderPass();//End GBuffer pass ++i; } //GBufferBarrier(cmd_buffer, gbuffer); } // void DeferredPass::DrawToAccum(vk::CommandBuffer cmd_buffer, PipelineThingy(&accum_stuff)[EGBufferType::size()], const CameraData& camera, [[maybe_unused]]RenderStateV2& rs) { int i = 0; auto sz = vec2{ camera.render_target->Size() }; auto viewport = rect{};// camera.viewport; for (auto& gbuffer : GBuffers()) { auto [offset, size] = ComputeVulkanViewport(sz, viewport); vk::Rect2D render_area { vk::Offset2D { s_cast(offset.x),s_cast(offset.y) },vk::Extent2D { s_cast(size.x),s_cast(size.y) } }; vk::ClearValue v[2] { vk::ClearColorValue{std::array{0.0f,0.0f,0.0f,0.0f}}, vk::ClearDepthStencilValue{1,0}, }; const auto& rp = accum_pass; vk::RenderPassBeginInfo rpbi { *rp, gbuffer.accum_buffer.as().GetFramebuffer(), render_area,hlp::arr_count(v),std::data(v) }; //Transit depth buffer to general for sampling //Begin Depthless RT renderpass cmd_buffer.beginRenderPass(rpbi, vk::SubpassContents::eInline); //Draw FSQ auto& dc = accum_stuff[i].DrawCalls(); RenderProcessedDrawCalls(cmd_buffer, dc, camera, pipeline_manager(), frame_index(), rpbi, rp, 1); //End Depthless RT renderpass cmd_buffer.endRenderPass(); ++i; } //Copy depth buffer to render target's depth buffer } void DoNothing(); void DeferredPass::DrawToRenderTarget(vk::CommandBuffer cmd_buffer, PipelineThingy& fsq_stuff,const CameraData& camera, [[maybe_unused]]VknRenderTarget& rt, [[maybe_unused]]RenderStateV2& rs) { auto sz = vec2{ camera.render_target->Size() }; auto [offset, size] = ComputeVulkanViewport(sz, camera.viewport); vk::Rect2D render_area { vk::Offset2D { s_cast(offset.x),s_cast(offset.y) },vk::Extent2D { s_cast(size.x),s_cast(size.y) } }; vk::ClearValue v[2] { vk::ClearColorValue{std::array{0.0f,0.0f,0.0f,0.0f}}, vk::ClearDepthStencilValue{1,0}, }; const auto& rp = hdr_pass; auto& fb = *hdr_buffer; ///vector formats; ///for (auto& b : fb.attachments) ///{ /// formats.emplace_back(b->buffer.as().format); ///} ///formats.emplace_back(rt.color_tex.as().format); ///formats.emplace_back(rt.depth_tex.as().format); vk::RenderPassBeginInfo rpbi { *rp, fb.GetFramebuffer(), render_area,hlp::arr_count(v),std::data(v) }; //if (formats[0] != formats[fb.attachments.size()]) // DoNothing(); //Transit depth buffer to general for sampling //Begin Depthless RT renderpass cmd_buffer.beginRenderPass(rpbi,vk::SubpassContents::eInline); //Draw FSQ RenderProcessedDrawCalls(cmd_buffer, fsq_stuff.DrawCalls(), camera, pipeline_manager(), frame_index(),rpbi,rp,1); //End Depthless RT renderpass cmd_buffer.endRenderPass(); //Copy depth buffer to render target's depth buffer //auto gbuffer_depth_img = GBuffer().gbuffer->DepthAttachment()->as().Image(); //PostRenderCopy(cmd_buffer, ivec2{ s_cast(render_area.extent.width),s_cast(render_area.extent.height) },rt.GetDepthBuffer().as().Image(), gbuffer_depth_img); } } #endif //returns color and depth