Commit a0aeb64e by Nicolas Capens Committed by Nicolas Capens

Fix multiview renderpass queries

The spec states that "If queries are used while executing a render pass instance that has multiview enabled, the query uses N consecutive query indices in the query pool (starting at query) where N is the number of bits set in the view mask in the subpass the query is used in. How the numerical results of the query are distributed among the queries is implementation-dependent. For example, some implementations may write each view’s results to a distinct query, while other implementations may write the total result to the first query and write zero to the other queries." This wasn't working properly for occlusion queries, but we missed it because dEQP doesn't provide coverage for this case if timestamp queries are not supported. This change fixes it for both query types. Note that for occlusion queries we write the total result to the first query, and set the remaining query results to 0, as explicitly allowed by the spec. For timestamp queries each query result is a valid timestamp (note that the spec also allows for only the first query to be a timestamp, while the remaining ones are zero). Bug: b/142643809 Change-Id: I531248c2822c5f68d8636d4a3d153082c48cac1d Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/53668 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com>
parent 69b79eec
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "marl/defer.h" #include "marl/defer.h"
#include <bitset>
#include <cstring> #include <cstring>
namespace { namespace {
...@@ -1059,16 +1060,24 @@ public: ...@@ -1059,16 +1060,24 @@ public:
void play(vk::CommandBuffer::ExecutionState &executionState) override void play(vk::CommandBuffer::ExecutionState &executionState) override
{ {
queryPool->begin(query, flags); // "If queries are used while executing a render pass instance that has multiview enabled, the query uses
// N consecutive query indices in the query pool (starting at `query`)"
for(uint32_t i = 0; i < executionState.viewCount(); i++)
{
queryPool->begin(query + i, flags);
}
// The renderer accumulates the result into a single query.
ASSERT(queryPool->getType() == VK_QUERY_TYPE_OCCLUSION);
executionState.renderer->addQuery(queryPool->getQuery(query)); executionState.renderer->addQuery(queryPool->getQuery(query));
} }
std::string description() override { return "vkCmdBeginQuery()"; } std::string description() override { return "vkCmdBeginQuery()"; }
private: private:
vk::QueryPool *queryPool; vk::QueryPool *const queryPool;
uint32_t query; const uint32_t query;
VkQueryControlFlags flags; const VkQueryControlFlags flags;
}; };
class CmdEndQuery : public vk::CommandBuffer::Command class CmdEndQuery : public vk::CommandBuffer::Command
...@@ -1082,15 +1091,27 @@ public: ...@@ -1082,15 +1091,27 @@ public:
void play(vk::CommandBuffer::ExecutionState &executionState) override void play(vk::CommandBuffer::ExecutionState &executionState) override
{ {
// The renderer accumulates the result into a single query.
ASSERT(queryPool->getType() == VK_QUERY_TYPE_OCCLUSION);
executionState.renderer->removeQuery(queryPool->getQuery(query)); executionState.renderer->removeQuery(queryPool->getQuery(query));
queryPool->end(query);
// "implementations may write the total result to the first query and write zero to the other queries."
for(uint32_t i = 1; i < executionState.viewCount(); i++)
{
queryPool->getQuery(query + i)->set(0);
}
for(uint32_t i = 0; i < executionState.viewCount(); i++)
{
queryPool->end(query + i);
}
} }
std::string description() override { return "vkCmdEndQuery()"; } std::string description() override { return "vkCmdEndQuery()"; }
private: private:
vk::QueryPool *queryPool; vk::QueryPool *const queryPool;
uint32_t query; const uint32_t query;
}; };
class CmdResetQueryPool : public vk::CommandBuffer::Command class CmdResetQueryPool : public vk::CommandBuffer::Command
...@@ -1139,15 +1160,20 @@ public: ...@@ -1139,15 +1160,20 @@ public:
executionState.renderer->synchronize(); executionState.renderer->synchronize();
} }
queryPool->writeTimestamp(query); // "the timestamp uses N consecutive query indices in the query pool (starting at `query`) where
// N is the number of bits set in the view mask of the subpass the command is executed in."
for(uint32_t i = 0; i < executionState.viewCount(); i++)
{
queryPool->writeTimestamp(query + i);
}
} }
std::string description() override { return "vkCmdWriteTimeStamp()"; } std::string description() override { return "vkCmdWriteTimeStamp()"; }
private: private:
vk::QueryPool *queryPool; vk::QueryPool *const queryPool;
uint32_t query; const uint32_t query;
VkPipelineStageFlagBits stage; const VkPipelineStageFlagBits stage;
}; };
class CmdCopyQueryPoolResults : public vk::CommandBuffer::Command class CmdCopyQueryPoolResults : public vk::CommandBuffer::Command
...@@ -1757,4 +1783,17 @@ void CommandBuffer::ExecutionState::bindAttachments(Attachments *attachments) ...@@ -1757,4 +1783,17 @@ void CommandBuffer::ExecutionState::bindAttachments(Attachments *attachments)
} }
} }
// Returns the number of bits set in the view mask, or 1 if multiview is disabled.
uint32_t CommandBuffer::ExecutionState::viewCount() const
{
uint32_t viewMask = 1;
if(renderPass)
{
viewMask = renderPass->getViewMask(subpassIndex);
}
return static_cast<uint32_t>(std::bitset<32>(viewMask).count());
}
} // namespace vk } // namespace vk
...@@ -165,6 +165,8 @@ public: ...@@ -165,6 +165,8 @@ public:
uint32_t subpassIndex = 0; uint32_t subpassIndex = 0;
void bindAttachments(Attachments *attachments); void bindAttachments(Attachments *attachments);
uint32_t viewCount() const;
}; };
void submit(CommandBuffer::ExecutionState &executionState); void submit(CommandBuffer::ExecutionState &executionState);
......
...@@ -99,12 +99,13 @@ public: ...@@ -99,12 +99,13 @@ public:
void writeTimestamp(uint32_t query); void writeTimestamp(uint32_t query);
inline Query *getQuery(uint32_t query) const { return &(pool[query]); } inline Query *getQuery(uint32_t query) const { return &pool[query]; }
inline VkQueryType getType() const { return type; }
private: private:
Query *pool; Query *const pool;
VkQueryType type; const VkQueryType type;
uint32_t count; const uint32_t count;
}; };
static inline QueryPool *Cast(VkQueryPool object) static inline QueryPool *Cast(VkQueryPool object)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment