Commit 7a1d99d0 by Nicolas Capens Committed by Nicolas Capens

Add a benchmark with multisampling enabled

This refactors the benchmarks to use static functions which support passing arbitrary arguments, instead of fixtures: https://github.com/google/benchmark#passing-arbitrary-arguments-to-a-benchmark This makes it easier to have a variant with and without multisampling, and avoids using state.counters[] as a hack to display clear formats. Bug: b/158231104 Change-Id: Icf0eed254dc942af8f2bcfc975a1e5e581b6e786 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/45790 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarAntonio Maiorano <amaiorano@google.com>
parent 7975aa43
...@@ -29,10 +29,10 @@ VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE ...@@ -29,10 +29,10 @@ VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include <cassert> #include <cassert>
#include <vector> #include <vector>
class VulkanBenchmark : public benchmark::Fixture class VulkanBenchmark
{ {
public: public:
void SetUp(::benchmark::State &state) override VulkanBenchmark()
{ {
// TODO(b/158231104): Other platforms // TODO(b/158231104): Other platforms
dl = std::make_unique<vk::DynamicLoader>("./vk_swiftshader.dll"); dl = std::make_unique<vk::DynamicLoader>("./vk_swiftshader.dll");
...@@ -63,7 +63,7 @@ public: ...@@ -63,7 +63,7 @@ public:
queue = device.getQueue(queueFamilyIndex, 0); queue = device.getQueue(queueFamilyIndex, 0);
} }
void TearDown(const ::benchmark::State &state) override virtual ~VulkanBenchmark()
{ {
device.waitIdle(); device.waitIdle();
device.destroy(); device.destroy();
...@@ -101,45 +101,14 @@ private: ...@@ -101,45 +101,14 @@ private:
std::unique_ptr<vk::DynamicLoader> dl; std::unique_ptr<vk::DynamicLoader> dl;
}; };
struct ClearBenchmarkVariant
{
vk::Format format;
const char *formatName;
vk::ImageAspectFlags aspect;
};
const std::vector<ClearBenchmarkVariant> clearBenchmarkVariants = {
{ vk::Format::eR8G8B8A8Unorm, "VK_FORMAT_R8G8B8A8_UNORM", vk::ImageAspectFlagBits::eColor },
{ vk::Format::eR32Sfloat, "VK_FORMAT_R32_SFLOAT", vk::ImageAspectFlagBits::eColor },
{ vk::Format::eD32Sfloat, "VK_FORMAT_D32_SFLOAT", vk::ImageAspectFlagBits::eDepth },
};
class ClearImageBenchmark : public VulkanBenchmark class ClearImageBenchmark : public VulkanBenchmark
{ {
public: public:
void SetUp(::benchmark::State &state) override ClearImageBenchmark(vk::Format clearFormat, vk::ImageAspectFlagBits clearAspect)
{
VulkanBenchmark::SetUp(state);
benchmark = clearBenchmarkVariants[state.range(0)];
state.counters[benchmark.formatName] = 1; // Small hack to display the format's name.
}
void TearDown(const ::benchmark::State &state) override
{ {
VulkanBenchmark::TearDown(state);
}
protected:
ClearBenchmarkVariant benchmark;
};
BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear)
(benchmark::State &state)
{
vk::ImageCreateInfo imageInfo; vk::ImageCreateInfo imageInfo;
imageInfo.imageType = vk::ImageType::e2D; imageInfo.imageType = vk::ImageType::e2D;
imageInfo.format = benchmark.format; imageInfo.format = clearFormat;
imageInfo.tiling = vk::ImageTiling::eOptimal; imageInfo.tiling = vk::ImageTiling::eOptimal;
imageInfo.initialLayout = vk::ImageLayout::eGeneral; imageInfo.initialLayout = vk::ImageLayout::eGeneral;
imageInfo.usage = vk::ImageUsageFlagBits::eTransferDst; imageInfo.usage = vk::ImageUsageFlagBits::eTransferDst;
...@@ -148,7 +117,7 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear) ...@@ -148,7 +117,7 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear)
imageInfo.mipLevels = 1; imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1; imageInfo.arrayLayers = 1;
vk::Image image = device.createImage(imageInfo); image = device.createImage(imageInfo);
vk::MemoryRequirements memoryRequirements = device.getImageMemoryRequirements(image); vk::MemoryRequirements memoryRequirements = device.getImageMemoryRequirements(image);
...@@ -156,20 +125,20 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear) ...@@ -156,20 +125,20 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear)
allocateInfo.allocationSize = memoryRequirements.size; allocateInfo.allocationSize = memoryRequirements.size;
allocateInfo.memoryTypeIndex = 0; allocateInfo.memoryTypeIndex = 0;
vk::DeviceMemory memory = device.allocateMemory(allocateInfo); memory = device.allocateMemory(allocateInfo);
device.bindImageMemory(image, memory, 0); device.bindImageMemory(image, memory, 0);
vk::CommandPoolCreateInfo commandPoolCreateInfo; vk::CommandPoolCreateInfo commandPoolCreateInfo;
commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex; commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex;
vk::CommandPool commandPool = device.createCommandPool(commandPoolCreateInfo); commandPool = device.createCommandPool(commandPoolCreateInfo);
vk::CommandBufferAllocateInfo commandBufferAllocateInfo; vk::CommandBufferAllocateInfo commandBufferAllocateInfo;
commandBufferAllocateInfo.commandPool = commandPool; commandBufferAllocateInfo.commandPool = commandPool;
commandBufferAllocateInfo.commandBufferCount = 1; commandBufferAllocateInfo.commandBufferCount = 1;
vk::CommandBuffer commandBuffer = device.allocateCommandBuffers(commandBufferAllocateInfo)[0]; commandBuffer = device.allocateCommandBuffers(commandBufferAllocateInfo)[0];
vk::CommandBufferBeginInfo commandBufferBeginInfo; vk::CommandBufferBeginInfo commandBufferBeginInfo;
commandBufferBeginInfo.flags = {}; commandBufferBeginInfo.flags = {};
...@@ -177,13 +146,13 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear) ...@@ -177,13 +146,13 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear)
commandBuffer.begin(commandBufferBeginInfo); commandBuffer.begin(commandBufferBeginInfo);
vk::ImageSubresourceRange range; vk::ImageSubresourceRange range;
range.aspectMask = benchmark.aspect; range.aspectMask = clearAspect;
range.baseMipLevel = 0; range.baseMipLevel = 0;
range.levelCount = 1; range.levelCount = 1;
range.baseArrayLayer = 0; range.baseArrayLayer = 0;
range.layerCount = 1; range.layerCount = 1;
if(benchmark.aspect == vk::ImageAspectFlagBits::eColor) if(clearAspect == vk::ImageAspectFlagBits::eColor)
{ {
vk::ClearColorValue clearColorValue; vk::ClearColorValue clearColorValue;
clearColorValue.float32[0] = 0.0f; clearColorValue.float32[0] = 0.0f;
...@@ -193,7 +162,7 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear) ...@@ -193,7 +162,7 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear)
commandBuffer.clearColorImage(image, vk::ImageLayout::eGeneral, &clearColorValue, 1, &range); commandBuffer.clearColorImage(image, vk::ImageLayout::eGeneral, &clearColorValue, 1, &range);
} }
else if(benchmark.aspect == vk::ImageAspectFlagBits::eDepth) else if(clearAspect == vk::ImageAspectFlagBits::eDepth)
{ {
vk::ClearDepthStencilValue clearDepthStencilValue; vk::ClearDepthStencilValue clearDepthStencilValue;
clearDepthStencilValue.depth = 1.0f; clearDepthStencilValue.depth = 1.0f;
...@@ -205,29 +174,49 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear) ...@@ -205,29 +174,49 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear)
assert(false); assert(false);
commandBuffer.end(); commandBuffer.end();
}
~ClearImageBenchmark()
{
device.freeCommandBuffers(commandPool, { commandBuffer });
device.destroyCommandPool(commandPool);
device.freeMemory(memory);
device.destroyImage(image);
}
void clear()
{
vk::SubmitInfo submitInfo; vk::SubmitInfo submitInfo;
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer; submitInfo.pCommandBuffers = &commandBuffer;
// Execute once to have the Reactor routine generated.
queue.submit(1, &submitInfo, nullptr); queue.submit(1, &submitInfo, nullptr);
queue.waitIdle(); queue.waitIdle();
}
private:
vk::CommandPool commandPool;
vk::CommandBuffer commandBuffer;
vk::Image image;
vk::DeviceMemory memory;
};
static void ClearImage(benchmark::State &state, vk::Format clearFormat, vk::ImageAspectFlagBits clearAspect)
{
ClearImageBenchmark benchmark(clearFormat, clearAspect);
// Execute once to have the Reactor routine generated.
benchmark.clear();
for(auto _ : state) for(auto _ : state)
{ {
queue.submit(1, &submitInfo, nullptr); benchmark.clear();
queue.waitIdle();
} }
device.freeCommandBuffers(commandPool, { commandBuffer });
device.destroyCommandPool(commandPool);
device.freeMemory(memory);
device.destroyImage(image);
} }
BENCHMARK_REGISTER_F(ClearImageBenchmark, Clear) BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_R8G8B8A8_UNORM, vk::Format::eR8G8B8A8Unorm, vk::ImageAspectFlagBits::eColor)->Unit(benchmark::kMillisecond);
->Unit(benchmark::kMillisecond) BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_R32_SFLOAT, vk::Format::eR32Sfloat, vk::ImageAspectFlagBits::eColor)->Unit(benchmark::kMillisecond);
->DenseRange(0, clearBenchmarkVariants.size() - 1, 1); BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_D32_SFLOAT, vk::Format::eD32Sfloat, vk::ImageAspectFlagBits::eDepth)->Unit(benchmark::kMillisecond);
class Window class Window
{ {
...@@ -541,10 +530,9 @@ static std::vector<uint32_t> compileGLSLtoSPIRV(const char *glslSource, EShLangu ...@@ -541,10 +530,9 @@ static std::vector<uint32_t> compileGLSLtoSPIRV(const char *glslSource, EShLangu
class TriangleBenchmark : public VulkanBenchmark class TriangleBenchmark : public VulkanBenchmark
{ {
public: public:
void SetUp(::benchmark::State &state) override TriangleBenchmark(bool multisample)
: multisample(multisample)
{ {
VulkanBenchmark::SetUp(state);
window = new Window(instance, windowSize); window = new Window(instance, windowSize);
swapchain = new Swapchain(physicalDevice, device, window); swapchain = new Swapchain(physicalDevice, device, window);
...@@ -560,7 +548,7 @@ public: ...@@ -560,7 +548,7 @@ public:
createCommandBuffers(renderPass); createCommandBuffers(renderPass);
} }
void TearDown(const ::benchmark::State &state) override ~TriangleBenchmark()
{ {
device.destroyPipelineLayout(pipelineLayout); device.destroyPipelineLayout(pipelineLayout);
device.destroyPipelineCache(pipelineCache); device.destroyPipelineCache(pipelineCache);
...@@ -588,8 +576,34 @@ public: ...@@ -588,8 +576,34 @@ public:
delete swapchain; delete swapchain;
delete window; delete window;
}
void renderFrame()
{
swapchain->acquireNextImage(presentCompleteSemaphore, currentFrameBuffer);
device.waitForFences(1, &waitFences[currentFrameBuffer], VK_TRUE, UINT64_MAX);
device.resetFences(1, &waitFences[currentFrameBuffer]);
vk::PipelineStageFlags waitStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
vk::SubmitInfo submitInfo;
submitInfo.pWaitDstStageMask = &waitStageMask;
submitInfo.pWaitSemaphores = &presentCompleteSemaphore;
submitInfo.waitSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &renderCompleteSemaphore;
submitInfo.signalSemaphoreCount = 1;
submitInfo.pCommandBuffers = &commandBuffers[currentFrameBuffer];
submitInfo.commandBufferCount = 1;
queue.submit(1, &submitInfo, waitFences[currentFrameBuffer]);
swapchain->queuePresent(queue, currentFrameBuffer, renderCompleteSemaphore);
}
VulkanBenchmark::TearDown(state); void show()
{
window->show();
} }
protected: protected:
...@@ -657,29 +671,6 @@ protected: ...@@ -657,29 +671,6 @@ protected:
} }
} }
void renderFrame()
{
swapchain->acquireNextImage(presentCompleteSemaphore, currentFrameBuffer);
device.waitForFences(1, &waitFences[currentFrameBuffer], VK_TRUE, UINT64_MAX);
device.resetFences(1, &waitFences[currentFrameBuffer]);
vk::PipelineStageFlags waitStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
vk::SubmitInfo submitInfo;
submitInfo.pWaitDstStageMask = &waitStageMask;
submitInfo.pWaitSemaphores = &presentCompleteSemaphore;
submitInfo.waitSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &renderCompleteSemaphore;
submitInfo.signalSemaphoreCount = 1;
submitInfo.pCommandBuffers = &commandBuffers[currentFrameBuffer];
submitInfo.commandBufferCount = 1;
queue.submit(1, &submitInfo, waitFences[currentFrameBuffer]);
swapchain->queuePresent(queue, currentFrameBuffer, renderCompleteSemaphore);
}
void prepareVertices() void prepareVertices()
{ {
struct Vertex struct Vertex
...@@ -933,7 +924,7 @@ protected: ...@@ -933,7 +924,7 @@ protected:
} }
const vk::Extent2D windowSize = { 1280, 720 }; const vk::Extent2D windowSize = { 1280, 720 };
const bool multisample = false; const bool multisample;
Window *window = nullptr; Window *window = nullptr;
Swapchain *swapchain = nullptr; Swapchain *swapchain = nullptr;
...@@ -965,18 +956,19 @@ protected: ...@@ -965,18 +956,19 @@ protected:
std::vector<vk::Fence> waitFences; std::vector<vk::Fence> waitFences;
}; };
BENCHMARK_DEFINE_F(TriangleBenchmark, Triangle) static void Triangle(benchmark::State &state, bool multisample)
(benchmark::State &state)
{ {
if(false) window->show(); // Enable for visual verification. TriangleBenchmark benchmark(multisample);
if(false) benchmark.show(); // Enable for visual verification.
// Warmup // Warmup
renderFrame(); benchmark.renderFrame();
for(auto _ : state) for(auto _ : state)
{ {
renderFrame(); benchmark.renderFrame();
} }
} }
BENCHMARK_REGISTER_F(TriangleBenchmark, Triangle) BENCHMARK_CAPTURE(Triangle, Hello, false)->Unit(benchmark::kMillisecond);
->Unit(benchmark::kMillisecond); BENCHMARK_CAPTURE(Triangle, Multisample, true)->Unit(benchmark::kMillisecond);
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