17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-09 03:58:55 +01:00

Walk the shadow passes and the culled model groups on worker threads in the Vulkan renderer

This commit is contained in:
2026-10-27 20:56:11 +01:00
parent c44b243698
commit 1447dcf075
55 changed files with 4114 additions and 427 deletions

View File

@@ -28,19 +28,31 @@ VkPipelineStageFlags2 const sampled_stage{VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BI
} // namespace
// the rendering of the map the maps set up last (begin(), begin_lamp(), begin_headlight()), and the pass of the walk into it
// the rendering of the map the maps set up last (begin(), begin_lamp(), begin_headlight()), and the pass of the walk into it: the map
// made ready for it (the states of the images are tracked by the main renderer), then begun (by the main renderer, or by a walker given
// the target, begin_local_shadow_target())
void vulkan14_renderer::begin_local_shadow_rendering()
{
m_draw->local_target = m_context->scene.lamps.target();
auto const &target{m_draw->local_target};
if ((target.map == nullptr) || (target.view == VK_NULL_HANDLE))
{
return;
}
vk14::barriers(m_commands, {vk14::use_of(*target.map, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, depth_stage, depth_access)});
}
void vulkan14_renderer::begin_local_shadow_target()
{
auto &ctx{*m_context};
auto &scene{ctx.scene};
auto const &target{scene.lamps.target()};
auto const commands{ctx.commands};
auto const &target{m_draw->local_target};
auto const commands{m_commands};
if ((target.map == nullptr) || (target.view == VK_NULL_HANDLE))
{
return;
}
auto const use{vk14::use_of(*target.map, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, depth_stage, depth_access)};
vk14::barriers(commands, {use});
VkRenderingAttachmentInfo depth{};
depth.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
depth.imageView = target.view;
@@ -70,7 +82,7 @@ void vulkan14_renderer::end_local_shadow_rendering()
{
if (m_draw->rendering)
{
m_context->commands->end_rendering();
m_commands->end_rendering();
}
end_draws();
}
@@ -89,7 +101,7 @@ void vulkan14_renderer::ready_lamp_maps()
}
if (false == uses.empty())
{
vk14::barriers(m_context->commands, uses);
vk14::barriers(m_commands, uses);
}
}
@@ -112,6 +124,7 @@ void vulkan14_renderer::render_local_shadows()
OpenGLMatrices.load_matrix(glm::mat4{glm::translate(glm::dmat4{1.0}, -glm::dvec3{lamps.lamp()}) * glm::inverse(vehicle->mMatrix)});
lamps.begin();
begin_local_shadow_rendering();
begin_local_shadow_target();
m_cubeshadows = true;
Render_cab(vehicle, 0.0f, false);
m_cubeshadows = false;
@@ -198,13 +211,46 @@ void vulkan14_renderer::render_lamp_shadow(std::size_t const Slot, bool const Ve
camera.update_frustum();
OpenGLMatrices.mode(GL_MODELVIEW);
OpenGLMatrices.load_matrix(glm::mat4{1.f});
lamps.begin_lamp(Slot, Vehicles, m_instancerecordsversion, m_framestamp);
begin_local_shadow_rendering();
// the vehicles by the lamp; or the scenery, with its instances culled on the gpu, each scenery part drawn in a frame with a culling
// of its own
std::vector<TDynamicObject *> vehicles;
vk14::instance_cull *cull{nullptr};
if (Vehicles)
{
vehicles = lamps.slot_vehicles();
}
else
{
cull = light_shadow_cull(m_context->scene.cull.lamps, m_lampscenerydrawn++, Global.gfx_gpucull_shadows_lamps);
}
auto const *owner{static_cast<TAnimModel const *>(slot.owner)};
if (walks_wanted())
{
// walked by a walker (gfx.vulkan.parallelpasses), its draws counted once it's done
fork_walk([target = m_draw->local_target, Vehicles, vehicles, Cab, owner, cull](vulkan14_renderer &Walker) {
Walker.m_draw->local_target = target;
Walker.walk_lamp(Vehicles, vehicles, Cab, owner, cull);
}, walk_kind::lamp);
lamps.end_lamp(0);
}
else
{
walk_lamp(Vehicles, vehicles, Cab, owner, cull);
lamps.end_lamp(static_cast<std::uint32_t>(m_renderpass.draw_stats.drawcalls));
}
m_renderpass = m_colorpass;
}
// the walk of the map of a lamp set up by render_lamp_shadow()
void vulkan14_renderer::walk_lamp(bool const Vehicles, std::vector<TDynamicObject *> const &Dynamics, TDynamicObject *Cab, TAnimModel const *Owner, vk14::instance_cull *Cull)
{
begin_local_shadow_target();
m_cubeshadows = true;
if (Vehicles)
{
for (auto *vehicle : lamps.slot_vehicles())
for (auto *vehicle : Dynamics)
{
Render(vehicle);
}
@@ -216,18 +262,15 @@ void vulkan14_renderer::render_lamp_shadow(std::size_t const Slot, bool const Ve
else
{
m_cubescenery = true;
m_cubeskipinstance = static_cast<TAnimModel const *>(slot.owner);
// the instances culled on the gpu, each scenery part drawn in a frame with a culling of its own
m_lightshadowcull = light_shadow_cull(m_context->scene.cull.lamps, m_lampscenerydrawn++, Global.gfx_gpucull_shadows_lamps);
Render(simulation::Region);
m_cubeskipinstance = Owner;
m_lightshadowcull = Cull;
walk_region(simulation::Region, false);
m_lightshadowcull = nullptr;
m_cubeskipinstance = nullptr;
m_cubescenery = false;
}
m_cubeshadows = false;
end_local_shadow_rendering();
lamps.end_lamp(static_cast<std::uint32_t>(m_renderpass.draw_stats.drawcalls));
m_renderpass = m_colorpass;
}
void vulkan14_renderer::render_headlight_shadows()
@@ -311,23 +354,46 @@ void vulkan14_renderer::render_headlight_shadow(std::size_t const Slot, light_ar
setup_matrices();
auto const colorprojection{scene_ubs.projection};
scene_ubs.projection = projection;
lamps.begin_headlight(Slot, projector, rotation, projection, Light.direction, m_framestamp);
begin_local_shadow_rendering();
m_shadowskipvehicle = Light.owner;
// the instances culled on the gpu, each slot with a culling of its own
m_lightshadowcull = light_shadow_cull(m_context->scene.cull.headlights, Slot, Global.gfx_gpucull_shadows_headlights);
Render(simulation::Region);
// the instances culled on the gpu, each slot with a culling of its own; the occupied cab, within the reach
auto *cull{light_shadow_cull(m_context->scene.cull.headlights, Slot, Global.gfx_gpucull_shadows_headlights)};
auto *cab{((Cab != nullptr) && (Cab != Light.owner) && (glm::length(Cab->GetPosition() - projector) <= reach + Cab->radius())) ? Cab : nullptr};
auto const *owner{Light.owner};
if (walks_wanted())
{
// walked by a walker (gfx.vulkan.parallelpasses), its draws counted once it's done
fork_walk([target = m_draw->local_target, owner, cab, cull](vulkan14_renderer &Walker) {
Walker.m_draw->local_target = target;
Walker.walk_headlight(owner, cab, cull);
}, walk_kind::headlight);
lamps.end_headlight(0);
}
else
{
walk_headlight(owner, cab, cull);
lamps.end_headlight(static_cast<std::uint32_t>(m_renderpass.draw_stats.drawcalls));
}
scene_ubs.projection = colorprojection;
m_renderpass = m_colorpass;
}
// the walk of the map of a set of headlights set up by render_headlight_shadow()
void vulkan14_renderer::walk_headlight(TDynamicObject const *Owner, TDynamicObject *Cab, vk14::instance_cull *Cull)
{
// the matrices of the projector (the walker's own, made from the pass it was given)
setup_matrices();
begin_local_shadow_target();
m_shadowskipvehicle = Owner;
m_lightshadowcull = Cull;
walk_region(simulation::Region, false);
m_lightshadowcull = nullptr;
if ((Cab != nullptr) && (Cab != Light.owner) && (glm::length(Cab->GetPosition() - projector) <= reach + Cab->radius()))
if (Cab != nullptr)
{
Render_cab(Cab, 0.0f, false);
}
m_shadowskipvehicle = nullptr;
end_local_shadow_rendering();
lamps.end_headlight(static_cast<std::uint32_t>(m_renderpass.draw_stats.drawcalls));
scene_ubs.projection = colorprojection;
m_renderpass = m_colorpass;
}
vk14::instance_cull *vulkan14_renderer::light_shadow_cull(std::vector<std::unique_ptr<vk14::instance_cull>> &Culls, std::size_t const Index, bool const Enabled)