Adding Pipeline statistics queries

This commit is contained in:
Dynamitos
2024-06-15 21:47:20 +02:00
parent 86c179e2e7
commit 0fd331b3b5
30 changed files with 344 additions and 95 deletions
+1 -1
View File
@@ -160,7 +160,7 @@ void BufferAllocation::readContents(uint64 regionOffset, uint64 regionSize, void
uint8* data;
VK_CHECK(vmaMapMemory(graphics->getAllocator(), staging->allocation, (void**)&data));
std::memcpy(buffer, data + regionOffset, regionSize);
std::memcpy(ptr, data + regionOffset, regionSize);
VK_CHECK(vmaFlushAllocation(graphics->getAllocator(), staging->allocation, regionOffset, regionSize));
vmaUnmapMemory(graphics->getAllocator(), staging->allocation);
graphics->getDestructionManager()->queueResourceForDestruction(std::move(staging));
+15 -11
View File
@@ -11,7 +11,7 @@
using namespace Seele;
using namespace Seele::Vulkan;
Command::Command(PGraphics graphics, PCommandPool pool) : graphics(graphics), pool(pool) {
Command::Command(PGraphics graphics, PCommandPool pool) : graphics(graphics), pool(pool), statisticsFlags(0) {
VkCommandBufferAllocateInfo allocInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.pNext = nullptr,
@@ -151,6 +151,9 @@ void Command::waitForCommand(uint32 timeout) {
checkFence();
}
void Command::setPipelineStatisticsFlags(VkQueryPipelineStatisticFlags flags)
{ statisticsFlags = flags; }
void Command::bindResource(PCommandBoundResource resource) {
resource->bind();
boundResources.add(resource);
@@ -173,7 +176,7 @@ RenderCommand::RenderCommand(PGraphics graphics, VkCommandPool cmdPool) : graphi
RenderCommand::~RenderCommand() { vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle); }
void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer) {
void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer, VkQueryPipelineStatisticFlags pipelineFlags) {
threadId = std::this_thread::get_id();
ready = false;
VkCommandBufferInheritanceInfo inheritanceInfo = {
@@ -181,9 +184,9 @@ void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer) {
.renderPass = renderPass->getHandle(),
.subpass = 0,
.framebuffer = framebuffer->getHandle(),
.occlusionQueryEnable = 1,
.queryFlags = VK_QUERY_CONTROL_PRECISE_BIT,
.pipelineStatistics = 0,
.occlusionQueryEnable = 0,
.queryFlags = 0,
.pipelineStatistics = pipelineFlags,
};
VkCommandBufferBeginInfo beginInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
@@ -323,7 +326,7 @@ ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool) : grap
ComputeCommand::~ComputeCommand() { vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle); }
void ComputeCommand::begin() {
void ComputeCommand::begin(VkQueryPipelineStatisticFlags pipelineFlags) {
threadId = std::this_thread::get_id();
ready = false;
VkCommandBufferInheritanceInfo inheritanceInfo = {
@@ -333,7 +336,7 @@ void ComputeCommand::begin() {
.framebuffer = VK_NULL_HANDLE,
.occlusionQueryEnable = 0,
.queryFlags = 0,
.pipelineStatistics = 0,
.pipelineStatistics = pipelineFlags,
};
VkCommandBufferBeginInfo beginInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
@@ -440,6 +443,7 @@ CommandPool::~CommandPool() {
}
PCommand CommandPool::getCommands() { return command; }
void CommandPool::cacheCommands(Array<ORenderCommand> commands) {
for (auto&& cmd : commands) {
allocatedRenderCommands.add(std::move(cmd));
@@ -458,13 +462,13 @@ ORenderCommand CommandPool::createRenderCommand(const std::string& name) {
ORenderCommand cmdBuffer = std::move(allocatedRenderCommands[i]);
allocatedRenderCommands.removeAt(i, false);
cmdBuffer->name = name;
cmdBuffer->begin(command->boundRenderPass, command->boundFramebuffer);
cmdBuffer->begin(command->boundRenderPass, command->boundFramebuffer, command->statisticsFlags);
return cmdBuffer;
}
}
ORenderCommand result = new RenderCommand(graphics, commandPool);
result->name = name;
result->begin(command->boundRenderPass, command->boundFramebuffer);
result->begin(command->boundRenderPass, command->boundFramebuffer, command->statisticsFlags);
return result;
}
@@ -474,13 +478,13 @@ OComputeCommand CommandPool::createComputeCommand(const std::string& name) {
OComputeCommand cmdBuffer = std::move(allocatedComputeCommands[i]);
allocatedComputeCommands.removeAt(i, false);
cmdBuffer->name = name;
cmdBuffer->begin();
cmdBuffer->begin(command->statisticsFlags);
return cmdBuffer;
}
}
OComputeCommand result = new ComputeCommand(graphics, commandPool);
result->name = name;
result->begin();
result->begin(command->statisticsFlags);
return result;
}
+4 -2
View File
@@ -29,6 +29,7 @@ class Command {
void bindResource(PCommandBoundResource resource);
void checkFence();
void waitForCommand(uint32 timeToWait = 1000000u);
void setPipelineStatisticsFlags(VkQueryPipelineStatisticFlags flags);
PFence getFence();
PCommandPool getPool();
enum State {
@@ -55,6 +56,7 @@ class Command {
Array<ORenderCommand> executingRenders;
Array<OComputeCommand> executingComputes;
Array<PDescriptorSet> boundResources;
VkQueryPipelineStatisticFlags statisticsFlags;
friend class RenderCommand;
friend class CommandPool;
friend class Queue;
@@ -68,7 +70,7 @@ class RenderCommand : public Gfx::RenderCommand {
RenderCommand(PGraphics graphics, VkCommandPool cmdPool);
virtual ~RenderCommand();
constexpr VkCommandBuffer getHandle() { return handle; }
void begin(PRenderPass renderPass, PFramebuffer framebuffer);
void begin(PRenderPass renderPass, PFramebuffer framebuffer, VkQueryPipelineStatisticFlags pipelineFlags);
void end();
void reset();
bool isReady();
@@ -103,7 +105,7 @@ class ComputeCommand : public Gfx::ComputeCommand {
ComputeCommand(PGraphics graphics, VkCommandPool cmdPool);
virtual ~ComputeCommand();
inline VkCommandBuffer getHandle() { return handle; }
void begin();
void begin(VkQueryPipelineStatisticFlags pipelineFlags);
void end();
void reset();
bool isReady();
+7 -20
View File
@@ -233,6 +233,8 @@ Gfx::OVertexInput Graphics::createVertexInput(VertexInputStateCreateInfo createI
Gfx::OOcclusionQuery Graphics::createOcclusionQuery() { return new OcclusionQuery(this); }
Gfx::OPipelineStatisticsQuery Graphics::createPipelineStatisticsQuery() { return new PipelineStatisticsQuery(this); }
void Graphics::resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) {
PTextureBase sourceTex = source.cast<TextureBase>();
PTextureBase destinationTex = destination.cast<TextureBase>();
@@ -287,16 +289,8 @@ void Graphics::copyTexture(Gfx::PTexture source, Gfx::PTexture destination) {
},
.srcOffsets =
{
{
0,
0,
0,
},
{
(int32)src->getWidth(),
(int32)src->getHeight(),
(int32)src->getDepth(),
},
{0, 0, 0},
{(int32)src->getWidth(), (int32)src->getHeight(), (int32)src->getDepth()},
},
.dstSubresource =
{
@@ -307,16 +301,8 @@ void Graphics::copyTexture(Gfx::PTexture source, Gfx::PTexture destination) {
},
.dstOffsets =
{
{
0,
0,
0,
},
{
(int32)dst->getWidth(),
(int32)dst->getHeight(),
(int32)dst->getDepth(),
},
{0, 0, 0},
{(int32)dst->getWidth(), (int32)dst->getHeight(), (int32)dst->getDepth()},
},
};
PCommand command = getGraphicsCommands()->getCommands();
@@ -517,6 +503,7 @@ void Graphics::pickPhysicalDevice() {
.fillModeNonSolid = true,
.wideLines = true,
.occlusionQueryPrecise = true,
.pipelineStatisticsQuery = true,
.fragmentStoresAndAtomics = true,
.shaderInt64 = true,
.inheritedQueries = true,
+1
View File
@@ -68,6 +68,7 @@ class Graphics : public Gfx::Graphics {
virtual Gfx::OVertexInput createVertexInput(VertexInputStateCreateInfo createInfo) override;
virtual Gfx::OOcclusionQuery createOcclusionQuery() override;
virtual Gfx::OPipelineStatisticsQuery createPipelineStatisticsQuery() override;
virtual void resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) override;
virtual void copyTexture(Gfx::PTexture src, Gfx::PTexture dst) override;
+98 -14
View File
@@ -1,32 +1,116 @@
#include "Query.h"
#include "Buffer.h"
#include "Command.h"
#include "Containers/Array.h"
#include "Enums.h"
#include "Graphics.h"
#include "Graphics/Query.h"
#include <vulkan/vulkan_core.h>
using namespace Seele;
using namespace Seele::Vulkan;
OcclusionQuery::OcclusionQuery(PGraphics graphics) :graphics(graphics){
QueryPool::QueryPool(PGraphics graphics, VkQueryType type, VkQueryPipelineStatisticFlags flags, uint32 resultsStride, uint32 numBuffered)
: graphics(graphics), flags(flags), numQueries(numBuffered), resultsStride(resultsStride) {
VkQueryPoolCreateInfo info = {
.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.queryType = VK_QUERY_TYPE_OCCLUSION,
.queryCount = 1,
.pipelineStatistics = 0,
.queryType = type,
.queryCount = numBuffered,
.pipelineStatistics = flags,
};
VK_CHECK(vkCreateQueryPool(graphics->getDevice(), &info, nullptr, &handle));
//VkBufferCreateInfo bufferInfo = {
// .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
// .pNext = nullptr,
// .flags = 0,
// .size = (resultsStride + 1) * numQueries * sizeof(uint64),
// .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
//};
//VmaAllocationCreateInfo allocInfo = {
// .flags = VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT,
// .usage = VMA_MEMORY_USAGE_AUTO,
// .requiredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
//};
//resultsAlloc = new BufferAllocation(graphics, "QueryResults", bufferInfo, allocInfo, Gfx::QueueType::GRAPHICS);
//VK_CHECK(vmaMapMemory(graphics->getAllocator(), resultsAlloc->allocation, (void**) & resultsPtr));
}
OcclusionQuery::~OcclusionQuery() { vkDestroyQueryPool(graphics->getDevice(), handle, nullptr); }
QueryPool::~QueryPool() { vkDestroyQueryPool(graphics->getDevice(), handle, nullptr); }
void OcclusionQuery::beginQuery() { vkCmdBeginQuery(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, 0, VK_QUERY_CONTROL_PRECISE_BIT); }
void QueryPool::begin() {
vkCmdResetQueryPool(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, currentQuery, 1);
vkCmdBeginQuery(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, currentQuery, 0);
graphics->getGraphicsCommands()->getCommands()->setPipelineStatisticsFlags(flags);
}
void OcclusionQuery::endQuery() { vkCmdEndQuery(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, 0); }
void OcclusionQuery::resetQuery() { vkCmdResetQueryPool(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, 0, 1); }
uint64 OcclusionQuery::getResults() {
void QueryPool::end() {
vkCmdEndQuery(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, currentQuery);
//vkCmdCopyQueryPoolResults(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, currentQuery, 1, resultsAlloc->buffer,
// sizeof(uint64) * currentQuery, resultsStride + sizeof(uint64),
// VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
graphics->getGraphicsCommands()->submitCommands();
uint64 result;
vkGetQueryPoolResults(graphics->getDevice(), handle, 0, 1, sizeof(uint64), &result, sizeof(uint64), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
return result;
currentQuery = (currentQuery + 1) % numQueries;
}
void QueryPool::getQueryResults(Array<uint64>& results) {
//uint64 numInts = resultsStride / sizeof(uint64);
while (currentQuery == pendingQuery)
;
results.resize(resultsStride/ sizeof(uint64));
vkGetQueryPoolResults(graphics->getDevice(), handle, pendingQuery, 1, resultsStride, results.data(), resultsStride,
VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT);
//uint64* currentPtr = resultsPtr + (pendingQuery * (numInts + 1));
//std::cout << pendingQuery << *(currentPtr + numInts) << std::endl;
//std::memcpy(results.data(), currentPtr, resultsStride);
pendingQuery = (pendingQuery + 1) % numQueries;
}
OcclusionQuery::OcclusionQuery(PGraphics graphics) : QueryPool(graphics, VK_QUERY_TYPE_OCCLUSION, 0, sizeof(uint64), 16) {}
OcclusionQuery::~OcclusionQuery() {}
void OcclusionQuery::beginQuery() { begin(); }
void OcclusionQuery::endQuery() { end(); }
Gfx::OcclusionResult OcclusionQuery::getResults() {
Array<uint64> result(1);
getQueryResults(result);
return Gfx::OcclusionResult{
.numFragments = result[0],
};
}
PipelineStatisticsQuery::PipelineStatisticsQuery(PGraphics graphics)
: QueryPool(graphics, VK_QUERY_TYPE_PIPELINE_STATISTICS,
VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT | VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT |
VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT | VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT |
VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT | VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT |
VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT |
VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT |
VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT,
sizeof(PipelineStatisticsQuery), 16) {}
PipelineStatisticsQuery::~PipelineStatisticsQuery() {}
void PipelineStatisticsQuery::beginQuery() { begin(); }
void PipelineStatisticsQuery::endQuery() { end(); }
Gfx::PipelineStatisticsResult PipelineStatisticsQuery::getResults() {
Array<uint64> result(9);
getQueryResults(result);
return Gfx::PipelineStatisticsResult{
.inputAssemblyVertices = result[0],
.inputAssemblyPrimitives = result[1],
.vertexShaderInvocations = result[2],
.clippingInvocations = result[3],
.clippingPrimitives = result[4],
.fragmentShaderInvocations = result[5],
.computeShaderInvocations = result[6],
.taskShaderInvocations = result[7],
.meshShaderInvocations = result[8],
};
}
+33 -7
View File
@@ -1,22 +1,48 @@
#pragma once
#include "Enums.h"
#include "Graphics.h"
#include "Graphics/Query.h"
#include "Buffer.h"
namespace Seele {
namespace Vulkan {
class OcclusionQuery : public Gfx::OcclusionQuery {
class QueryPool {
public:
QueryPool(PGraphics graphics, VkQueryType type, VkQueryPipelineStatisticFlags flags, uint32 resultsStride, uint32 numBuffered);
virtual ~QueryPool();
void begin();
void end();
// stalls for the currently first pending query, dont call in render thread
void getQueryResults(Array<uint64>& results);
protected:
PGraphics graphics;
VkQueryPool handle;
VkQueryPipelineStatisticFlags flags;
OBufferAllocation resultsAlloc;
uint64* resultsPtr;
uint32 pendingQuery = 0;
uint32 currentQuery = 0;
uint32 numQueries;
uint32 resultsStride;
};
class OcclusionQuery : public Gfx::OcclusionQuery, public QueryPool {
public:
OcclusionQuery(PGraphics graphics);
virtual ~OcclusionQuery();
virtual void beginQuery() override;
virtual void endQuery() override;
virtual void resetQuery() override;
virtual uint64 getResults() override;
private:
PGraphics graphics;
VkQueryPool handle;
virtual Gfx::OcclusionResult getResults() override;
};
DEFINE_REF(OcclusionQuery)
class PipelineStatisticsQuery : public Gfx::PipelineStatisticsQuery, public QueryPool {
public:
PipelineStatisticsQuery(PGraphics graphics);
virtual ~PipelineStatisticsQuery();
virtual void beginQuery() override;
virtual void endQuery() override;
virtual Gfx::PipelineStatisticsResult getResults() override;
};
DEFINE_REF(PipelineStatisticsQuery)
} // namespace Vulkan
} // namespace Seele