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:
@@ -79,6 +79,21 @@ void barriers(command_stream *Commands, std::vector<image_use> const &Uses)
|
||||
Commands->pipeline_barrier2(&dependency);
|
||||
}
|
||||
|
||||
void barriers_again(command_stream *Commands, std::vector<image_use> const &Uses)
|
||||
{
|
||||
// what barriers() makes of a use following the same use
|
||||
std::vector<image_use> uses;
|
||||
std::vector<image_state> states(Uses.size());
|
||||
for (std::size_t i = 0; i < Uses.size(); ++i)
|
||||
{
|
||||
auto use{Uses[i]};
|
||||
states[i] = image_state{use.layout, use.stage, use.access};
|
||||
use.state = &states[i];
|
||||
uses.push_back(use);
|
||||
}
|
||||
barriers(Commands, uses);
|
||||
}
|
||||
|
||||
pass_list::~pass_list()
|
||||
{
|
||||
destroy();
|
||||
@@ -95,6 +110,8 @@ bool pass_list::create(device const &Device, std::uint32_t Frames, std::string &
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(Device.physical(), &count, families.data());
|
||||
auto const bits{(Device.families().graphics < count) ? families[Device.families().graphics].timestampValidBits : 64u};
|
||||
m_mask = (bits >= 64 ? ~0ull : ((1ull << bits) - 1));
|
||||
auto const asyncbits{(Device.families().compute < count) ? families[Device.families().compute].timestampValidBits : 64u};
|
||||
m_asyncmask = (asyncbits >= 64 ? ~0ull : ((1ull << asyncbits) - 1));
|
||||
|
||||
m_frames.resize(Frames);
|
||||
for (std::uint32_t i = 0; i < Frames; ++i)
|
||||
@@ -112,6 +129,15 @@ bool pass_list::create(device const &Device, std::uint32_t Frames, std::string &
|
||||
// the queries are reset from the host before their first use (hostQueryReset)
|
||||
vkResetQueryPool(m_device, m_frames[i].pool, 0, info.queryCount);
|
||||
name_object(m_device, VK_OBJECT_TYPE_QUERY_POOL, handle_value(m_frames[i].pool), "pass times " + std::to_string(i));
|
||||
info.queryCount = max_async * 2;
|
||||
if (!VK14_VERIFY(vkCreateQueryPool(m_device, &info, nullptr, &m_frames[i].async_pool)))
|
||||
{
|
||||
m_frames[i].async_pool = VK_NULL_HANDLE;
|
||||
Reason = "no query pool for the times of the passes";
|
||||
return false;
|
||||
}
|
||||
vkResetQueryPool(m_device, m_frames[i].async_pool, 0, info.queryCount);
|
||||
name_object(m_device, VK_OBJECT_TYPE_QUERY_POOL, handle_value(m_frames[i].async_pool), "async pass times " + std::to_string(i));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -124,6 +150,10 @@ void pass_list::destroy()
|
||||
{
|
||||
vkDestroyQueryPool(m_device, frame.pool, nullptr);
|
||||
}
|
||||
if (frame.async_pool != VK_NULL_HANDLE)
|
||||
{
|
||||
vkDestroyQueryPool(m_device, frame.async_pool, nullptr);
|
||||
}
|
||||
}
|
||||
m_frames.clear();
|
||||
m_device = VK_NULL_HANDLE;
|
||||
@@ -132,6 +162,8 @@ void pass_list::destroy()
|
||||
void pass_list::begin_frame(command_stream *Commands, std::uint32_t Frame, std::uint64_t Number)
|
||||
{
|
||||
m_commands = Commands;
|
||||
m_graphics = nullptr;
|
||||
m_async = false;
|
||||
m_frame = Frame;
|
||||
m_open = -1;
|
||||
auto &frame{m_frames[Frame]};
|
||||
@@ -140,6 +172,14 @@ void pass_list::begin_frame(command_stream *Commands, std::uint32_t Frame, std::
|
||||
frame.number = Number;
|
||||
frame.recorded = true;
|
||||
Commands->reset_query_pool(frame.pool, 0, max_passes * 2);
|
||||
// the gpu is done with the frame which used the slot before: the queries of the compute queue are reset from here, the queue may
|
||||
// write them before the graphics queue gets to a reset of its own
|
||||
if (frame.async_used > 0)
|
||||
{
|
||||
vkResetQueryPool(m_device, frame.async_pool, 0, max_async * 2);
|
||||
}
|
||||
frame.async_names.clear();
|
||||
frame.async_used = 0;
|
||||
}
|
||||
|
||||
void pass_list::begin_pass(char const *Name, std::vector<image_use> const &Uses)
|
||||
@@ -151,6 +191,21 @@ void pass_list::begin_pass(char const *Name, std::vector<image_use> const &Uses)
|
||||
barriers(m_commands, Uses);
|
||||
begin_label(m_commands, Name);
|
||||
auto &frame{m_frames[m_frame]};
|
||||
if (m_async)
|
||||
{
|
||||
if ((frame.async_used < max_async) && (m_asyncmask != 0))
|
||||
{
|
||||
m_commands->write_timestamp2(VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, frame.async_pool, frame.async_used * 2);
|
||||
frame.async_names.emplace_back(Name);
|
||||
m_open = static_cast<int>(frame.async_used);
|
||||
++frame.async_used;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_open = static_cast<int>(max_passes);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// (no timestamps on a queue without valid bits; the device is chosen with them, this is for safety)
|
||||
if ((frame.used < max_passes) && (m_mask != 0))
|
||||
{
|
||||
@@ -173,14 +228,39 @@ void pass_list::end_pass()
|
||||
}
|
||||
if (m_open < static_cast<int>(max_passes))
|
||||
{
|
||||
m_commands->write_timestamp2(VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, m_frames[m_frame].pool, static_cast<std::uint32_t>(m_open) * 2 + 1);
|
||||
m_commands->write_timestamp2(VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, m_async ? m_frames[m_frame].async_pool : m_frames[m_frame].pool, static_cast<std::uint32_t>(m_open) * 2 + 1);
|
||||
}
|
||||
end_label(m_commands);
|
||||
m_open = -1;
|
||||
}
|
||||
|
||||
void pass_list::begin_async(command_stream *Commands)
|
||||
{
|
||||
end_pass();
|
||||
if (m_async)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_graphics = m_commands;
|
||||
m_commands = Commands;
|
||||
m_async = true;
|
||||
}
|
||||
|
||||
void pass_list::end_async()
|
||||
{
|
||||
end_pass();
|
||||
if (false == m_async)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_commands = m_graphics;
|
||||
m_graphics = nullptr;
|
||||
m_async = false;
|
||||
}
|
||||
|
||||
void pass_list::end_frame()
|
||||
{
|
||||
end_async();
|
||||
end_pass();
|
||||
m_commands = nullptr;
|
||||
}
|
||||
@@ -193,14 +273,34 @@ void pass_list::collect(std::uint32_t Frame)
|
||||
return;
|
||||
}
|
||||
frame.recorded = false;
|
||||
// a running average, so the numbers can be read
|
||||
auto const blend = [](double &Average, double const Value) { Average = (Average <= 0.0 ? Value : Average * 0.9 + Value * 0.1); };
|
||||
// the passes of the compute queue, apart
|
||||
if (frame.async_used > 0)
|
||||
{
|
||||
std::vector<std::uint64_t> stamps(frame.async_used * 2);
|
||||
if (vkGetQueryPoolResults(m_device, frame.async_pool, 0, frame.async_used * 2, stamps.size() * sizeof(std::uint64_t), stamps.data(), sizeof(std::uint64_t), VK_QUERY_RESULT_64_BIT) == VK_SUCCESS)
|
||||
{
|
||||
for (std::uint32_t i = 0; i < frame.async_used; ++i)
|
||||
{
|
||||
auto const ticks{((stamps[i * 2 + 1] & m_asyncmask) - (stamps[i * 2] & m_asyncmask)) & m_asyncmask};
|
||||
auto const name{frame.async_names[i] + " (async)"};
|
||||
auto lookup{std::find_if(m_asynctimes.begin(), m_asynctimes.end(), [&](auto const &Entry) { return Entry.first == name; })};
|
||||
if (lookup == m_asynctimes.end())
|
||||
{
|
||||
m_asynctimes.emplace_back(name, 0.0);
|
||||
lookup = std::prev(m_asynctimes.end());
|
||||
}
|
||||
blend(lookup->second, static_cast<double>(ticks) * m_period / 1000000.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<std::uint64_t> stamps(frame.used * 2);
|
||||
auto const result{vkGetQueryPoolResults(m_device, frame.pool, 0, frame.used * 2, stamps.size() * sizeof(std::uint64_t), stamps.data(), sizeof(std::uint64_t), VK_QUERY_RESULT_64_BIT)};
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// a running average, so the numbers can be read
|
||||
auto const blend = [](double &Average, double const Value) { Average = (Average <= 0.0 ? Value : Average * 0.9 + Value * 0.1); };
|
||||
double total{0.0};
|
||||
for (std::uint32_t i = 0; i < frame.used; ++i)
|
||||
{
|
||||
@@ -246,6 +346,11 @@ std::string pass_list::info() const
|
||||
}
|
||||
std::snprintf(buffer, sizeof(buffer), " %-14s %7.3f ms\n", "total", m_framems);
|
||||
text += buffer;
|
||||
for (auto const &[name, ms] : m_asynctimes)
|
||||
{
|
||||
std::snprintf(buffer, sizeof(buffer), " %-14s %7.3f ms\n", name.c_str(), ms);
|
||||
text += buffer;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user