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
#include <cassert>
#include <vector>
class VulkanBenchmark : public benchmark::Fixture
class VulkanBenchmark
{
public:
void SetUp(::benchmark::State &state) override
VulkanBenchmark()
{
// TODO(b/158231104): Other platforms
dl = std::make_unique<vk::DynamicLoader>("./vk_swiftshader.dll");
......@@ -63,7 +63,7 @@ public:
queue = device.getQueue(queueFamilyIndex, 0);
}
void TearDown(const ::benchmark::State &state) override
virtual ~VulkanBenchmark()
{
device.waitIdle();
device.destroy();
......@@ -101,45 +101,14 @@ private:
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
{
public:
void SetUp(::benchmark::State &state) override
{
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
ClearImageBenchmark(vk::Format clearFormat, vk::ImageAspectFlagBits clearAspect)
{
VulkanBenchmark::TearDown(state);
}
protected:
ClearBenchmarkVariant benchmark;
};
BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear)
(benchmark::State &state)
{
vk::ImageCreateInfo imageInfo;
imageInfo.imageType = vk::ImageType::e2D;
imageInfo.format = benchmark.format;
imageInfo.format = clearFormat;
imageInfo.tiling = vk::ImageTiling::eOptimal;
imageInfo.initialLayout = vk::ImageLayout::eGeneral;
imageInfo.usage = vk::ImageUsageFlagBits::eTransferDst;
......@@ -148,7 +117,7 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear)
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
vk::Image image = device.createImage(imageInfo);
image = device.createImage(imageInfo);
vk::MemoryRequirements memoryRequirements = device.getImageMemoryRequirements(image);
......@@ -156,20 +125,20 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear)
allocateInfo.allocationSize = memoryRequirements.size;
allocateInfo.memoryTypeIndex = 0;
vk::DeviceMemory memory = device.allocateMemory(allocateInfo);
memory = device.allocateMemory(allocateInfo);
device.bindImageMemory(image, memory, 0);
vk::CommandPoolCreateInfo commandPoolCreateInfo;
commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex;
vk::CommandPool commandPool = device.createCommandPool(commandPoolCreateInfo);
commandPool = device.createCommandPool(commandPoolCreateInfo);
vk::CommandBufferAllocateInfo commandBufferAllocateInfo;
commandBufferAllocateInfo.commandPool = commandPool;
commandBufferAllocateInfo.commandBufferCount = 1;
vk::CommandBuffer commandBuffer = device.allocateCommandBuffers(commandBufferAllocateInfo)[0];
commandBuffer = device.allocateCommandBuffers(commandBufferAllocateInfo)[0];
vk::CommandBufferBeginInfo commandBufferBeginInfo;
commandBufferBeginInfo.flags = {};
......@@ -177,13 +146,13 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear)
commandBuffer.begin(commandBufferBeginInfo);
vk::ImageSubresourceRange range;
range.aspectMask = benchmark.aspect;
range.aspectMask = clearAspect;
range.baseMipLevel = 0;
range.levelCount = 1;
range.baseArrayLayer = 0;
range.layerCount = 1;
if(benchmark.aspect == vk::ImageAspectFlagBits::eColor)
if(clearAspect == vk::ImageAspectFlagBits::eColor)
{
vk::ClearColorValue clearColorValue;
clearColorValue.float32[0] = 0.0f;
......@@ -193,7 +162,7 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear)
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;
clearDepthStencilValue.depth = 1.0f;
......@@ -205,29 +174,49 @@ BENCHMARK_DEFINE_F(ClearImageBenchmark, Clear)
assert(false);
commandBuffer.end();
}
~ClearImageBenchmark()
{
device.freeCommandBuffers(commandPool, { commandBuffer });
device.destroyCommandPool(commandPool);
device.freeMemory(memory);
device.destroyImage(image);
}
void clear()
{
vk::SubmitInfo submitInfo;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
// Execute once to have the Reactor routine generated.
queue.submit(1, &submitInfo, nullptr);
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)
{
queue.submit(1, &submitInfo, nullptr);
queue.waitIdle();
benchmark.clear();
}
device.freeCommandBuffers(commandPool, { commandBuffer });
device.destroyCommandPool(commandPool);
device.freeMemory(memory);
device.destroyImage(image);
}
BENCHMARK_REGISTER_F(ClearImageBenchmark, Clear)
->Unit(benchmark::kMillisecond)
->DenseRange(0, clearBenchmarkVariants.size() - 1, 1);
BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_R8G8B8A8_UNORM, vk::Format::eR8G8B8A8Unorm, vk::ImageAspectFlagBits::eColor)->Unit(benchmark::kMillisecond);
BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_R32_SFLOAT, vk::Format::eR32Sfloat, vk::ImageAspectFlagBits::eColor)->Unit(benchmark::kMillisecond);
BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_D32_SFLOAT, vk::Format::eD32Sfloat, vk::ImageAspectFlagBits::eDepth)->Unit(benchmark::kMillisecond);
class Window
{
......@@ -541,10 +530,9 @@ static std::vector<uint32_t> compileGLSLtoSPIRV(const char *glslSource, EShLangu
class TriangleBenchmark : public VulkanBenchmark
{
public:
void SetUp(::benchmark::State &state) override
TriangleBenchmark(bool multisample)
: multisample(multisample)
{
VulkanBenchmark::SetUp(state);
window = new Window(instance, windowSize);
swapchain = new Swapchain(physicalDevice, device, window);
......@@ -560,7 +548,7 @@ public:
createCommandBuffers(renderPass);
}
void TearDown(const ::benchmark::State &state) override
~TriangleBenchmark()
{
device.destroyPipelineLayout(pipelineLayout);
device.destroyPipelineCache(pipelineCache);
......@@ -588,8 +576,34 @@ public:
delete swapchain;
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:
......@@ -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()
{
struct Vertex
......@@ -933,7 +924,7 @@ protected:
}
const vk::Extent2D windowSize = { 1280, 720 };
const bool multisample = false;
const bool multisample;
Window *window = nullptr;
Swapchain *swapchain = nullptr;
......@@ -965,18 +956,19 @@ protected:
std::vector<vk::Fence> waitFences;
};
BENCHMARK_DEFINE_F(TriangleBenchmark, Triangle)
(benchmark::State &state)
static void Triangle(benchmark::State &state, bool multisample)
{
if(false) window->show(); // Enable for visual verification.
TriangleBenchmark benchmark(multisample);
if(false) benchmark.show(); // Enable for visual verification.
// Warmup
renderFrame();
benchmark.renderFrame();
for(auto _ : state)
{
renderFrame();
benchmark.renderFrame();
}
}
BENCHMARK_REGISTER_F(TriangleBenchmark, Triangle)
->Unit(benchmark::kMillisecond);
BENCHMARK_CAPTURE(Triangle, Hello, false)->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