VulkanBenchmarks: split out benchmark classes into separate files

* Move out VulkanBenchmark and DrawBenchmark classes to their own hpp/cpps. * Move out ClearImageBenchmark and TriangleBenchmark classes and tests to their own cpps. * Add non-template DrawBenchmark::addVertexBuffer that takes the size of the vertex type. This allows for the implementation to be moved to the cpp file, keeping the header light and easy to understand. Bug: b/176981107 Change-Id: I657bd112c5523aa56dc5617082d6744b9edac03a Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/52130 Kokoro-Result: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarAntonio Maiorano <amaiorano@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com>
parent ea1f7d10
...@@ -22,8 +22,13 @@ set(ROOT_PROJECT_LINK_LIBRARIES ...@@ -22,8 +22,13 @@ set(ROOT_PROJECT_LINK_LIBRARIES
) )
set(VULKAN_BENCHMARKS_SRC_FILES set(VULKAN_BENCHMARKS_SRC_FILES
ClearImageBenchmarks.cpp
DrawBenchmark.cpp
DrawBenchmark.hpp
main.cpp main.cpp
VulkanBenchmarks.cpp TriangleBenchmarks.cpp
VulkanBenchmark.cpp
VulkanBenchmark.hpp
) )
add_executable(VulkanBenchmarks add_executable(VulkanBenchmarks
......
// Copyright 2021 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "VulkanBenchmark.hpp"
#include "benchmark/benchmark.h"
#include <cassert>
class ClearImageBenchmark : public VulkanBenchmark
{
public:
void initialize(vk::Format clearFormat, vk::ImageAspectFlagBits clearAspect)
{
VulkanBenchmark::initialize();
vk::ImageCreateInfo imageInfo;
imageInfo.imageType = vk::ImageType::e2D;
imageInfo.format = clearFormat;
imageInfo.tiling = vk::ImageTiling::eOptimal;
imageInfo.initialLayout = vk::ImageLayout::eGeneral;
imageInfo.usage = vk::ImageUsageFlagBits::eTransferDst;
imageInfo.samples = vk::SampleCountFlagBits::e4;
imageInfo.extent = vk::Extent3D(1024, 1024, 1);
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
image = device.createImage(imageInfo);
vk::MemoryRequirements memoryRequirements = device.getImageMemoryRequirements(image);
vk::MemoryAllocateInfo allocateInfo;
allocateInfo.allocationSize = memoryRequirements.size;
allocateInfo.memoryTypeIndex = 0;
memory = device.allocateMemory(allocateInfo);
device.bindImageMemory(image, memory, 0);
vk::CommandPoolCreateInfo commandPoolCreateInfo;
commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex;
commandPool = device.createCommandPool(commandPoolCreateInfo);
vk::CommandBufferAllocateInfo commandBufferAllocateInfo;
commandBufferAllocateInfo.commandPool = commandPool;
commandBufferAllocateInfo.commandBufferCount = 1;
commandBuffer = device.allocateCommandBuffers(commandBufferAllocateInfo)[0];
vk::CommandBufferBeginInfo commandBufferBeginInfo;
commandBufferBeginInfo.flags = {};
commandBuffer.begin(commandBufferBeginInfo);
vk::ImageSubresourceRange range;
range.aspectMask = clearAspect;
range.baseMipLevel = 0;
range.levelCount = 1;
range.baseArrayLayer = 0;
range.layerCount = 1;
if(clearAspect == vk::ImageAspectFlagBits::eColor)
{
vk::ClearColorValue clearColorValue;
clearColorValue.float32[0] = 0.0f;
clearColorValue.float32[1] = 1.0f;
clearColorValue.float32[2] = 0.0f;
clearColorValue.float32[3] = 1.0f;
commandBuffer.clearColorImage(image, vk::ImageLayout::eGeneral, &clearColorValue, 1, &range);
}
else if(clearAspect == vk::ImageAspectFlagBits::eDepth)
{
vk::ClearDepthStencilValue clearDepthStencilValue;
clearDepthStencilValue.depth = 1.0f;
clearDepthStencilValue.stencil = 0xFF;
commandBuffer.clearDepthStencilImage(image, vk::ImageLayout::eGeneral, &clearDepthStencilValue, 1, &range);
}
else
assert(false);
commandBuffer.end();
}
~ClearImageBenchmark()
{
device.freeCommandBuffers(commandPool, 1, &commandBuffer);
device.destroyCommandPool(commandPool, nullptr);
device.freeMemory(memory, nullptr);
device.destroyImage(image, nullptr);
}
void clear()
{
vk::SubmitInfo submitInfo;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
queue.submit(1, &submitInfo, nullptr);
queue.waitIdle();
}
private:
vk::Image image; // Owning handle
vk::DeviceMemory memory; // Owning handle
vk::CommandPool commandPool; // Owning handle
vk::CommandBuffer commandBuffer; // Owning handle
};
static void ClearImage(benchmark::State &state, vk::Format clearFormat, vk::ImageAspectFlagBits clearAspect)
{
ClearImageBenchmark benchmark;
benchmark.initialize(clearFormat, clearAspect);
// Execute once to have the Reactor routine generated.
benchmark.clear();
for(auto _ : state)
{
benchmark.clear();
}
}
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);
// Copyright 2021 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef DRAW_BENCHMARK_HPP_
#define DRAW_BENCHMARK_HPP_
#include "Framebuffer.hpp"
#include "Image.hpp"
#include "Swapchain.hpp"
#include "Util.hpp"
#include "VulkanBenchmark.hpp"
#include "Window.hpp"
enum class Multisample
{
False,
True
};
class DrawBenchmark : public VulkanBenchmark
{
public:
DrawBenchmark(Multisample multisample);
~DrawBenchmark();
void initialize();
void renderFrame();
void show();
private:
void createSynchronizationPrimitives();
void createCommandBuffers(vk::RenderPass renderPass);
void prepareVertices();
void createFramebuffers(vk::RenderPass renderPass);
vk::RenderPass createRenderPass(vk::Format colorFormat);
vk::Pipeline createGraphicsPipeline(vk::RenderPass renderPass);
void addVertexBuffer(void *vertexBufferData, size_t vertexBufferDataSize, size_t vertexSize, std::vector<vk::VertexInputAttributeDescription> inputAttributes);
protected:
/////////////////////////
// Hooks
/////////////////////////
// Called from prepareVertices.
// Child type may call addVertexBuffer() from this function.
virtual void doCreateVertexBuffers() {}
// Called from createGraphicsPipeline.
// Child type may return vector of DescriptorSetLayoutBindings for which a DescriptorSetLayout
// will be created and stored in this->descriptorSetLayout.
virtual std::vector<vk::DescriptorSetLayoutBinding> doCreateDescriptorSetLayouts()
{
return {};
}
// Called from createGraphicsPipeline.
// Child type may call createShaderModule() and return the result.
virtual vk::ShaderModule doCreateVertexShader()
{
return nullptr;
}
// Called from createGraphicsPipeline.
// Child type may call createShaderModule() and return the result.
virtual vk::ShaderModule doCreateFragmentShader()
{
return nullptr;
}
// Called from createCommandBuffers.
// Child type may create resources (addImage, addSampler, etc.), and make sure to
// call device.updateDescriptorSets.
virtual void doUpdateDescriptorSet(vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet)
{
}
/////////////////////////
// Resource Management
/////////////////////////
// Call from doCreateFragmentShader()
vk::ShaderModule createShaderModule(const char *glslSource, EShLanguage glslLanguage);
// Call from doCreateVertexBuffers()
template<typename VertexType>
void addVertexBuffer(VertexType *vertexBufferData, size_t vertexBufferDataSize, std::vector<vk::VertexInputAttributeDescription> inputAttributes)
{
addVertexBuffer(vertexBufferData, vertexBufferDataSize, sizeof(VertexType), std::move(inputAttributes));
}
template<typename T>
struct Resource
{
size_t id;
T &obj;
};
template<typename... Args>
Resource<Image> addImage(Args &&... args)
{
images.emplace_back(std::make_unique<Image>(std::forward<Args>(args)...));
return { images.size() - 1, *images.back() };
}
Image &getImageById(size_t id)
{
return *images[id].get();
}
Resource<vk::Sampler> addSampler(const vk::SamplerCreateInfo &samplerCreateInfo)
{
auto sampler = device.createSampler(samplerCreateInfo);
samplers.push_back(sampler);
return { samplers.size() - 1, sampler };
}
vk::Sampler &getSamplerById(size_t id)
{
return samplers[id];
}
private:
const vk::Extent2D windowSize = { 1280, 720 };
const bool multisample;
std::unique_ptr<Window> window;
std::unique_ptr<Swapchain> swapchain;
vk::RenderPass renderPass; // Owning handle
std::vector<std::unique_ptr<Framebuffer>> framebuffers;
uint32_t currentFrameBuffer = 0;
struct VertexBuffer
{
vk::Buffer buffer; // Owning handle
vk::DeviceMemory memory; // Owning handle
vk::VertexInputBindingDescription inputBinding;
std::vector<vk::VertexInputAttributeDescription> inputAttributes;
vk::PipelineVertexInputStateCreateInfo inputState;
uint32_t numVertices;
} vertices;
vk::DescriptorSetLayout descriptorSetLayout; // Owning handle
vk::PipelineLayout pipelineLayout; // Owning handle
vk::Pipeline pipeline; // Owning handle
vk::Semaphore presentCompleteSemaphore; // Owning handle
vk::Semaphore renderCompleteSemaphore; // Owning handle
std::vector<vk::Fence> waitFences; // Owning handles
vk::CommandPool commandPool; // Owning handle
vk::DescriptorPool descriptorPool; // Owning handle
// Resources
std::vector<std::unique_ptr<Image>> images;
std::vector<vk::Sampler> samplers; // Owning handles
std::vector<vk::CommandBuffer> commandBuffers; // Owning handles
};
#endif // DRAW_BENCHMARK_HPP_
// Copyright 2021 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "VulkanBenchmark.hpp"
VulkanBenchmark::~VulkanBenchmark()
{
device.waitIdle();
device.destroy(nullptr);
instance.destroy(nullptr);
}
void VulkanBenchmark::initialize()
{
// TODO(b/158231104): Other platforms
#if defined(_WIN32)
dl = std::make_unique<vk::DynamicLoader>("./vk_swiftshader.dll");
#elif defined(__linux__)
dl = std::make_unique<vk::DynamicLoader>("./libvk_swiftshader.so");
#else
# error Unimplemented platform
#endif
assert(dl->success());
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl->getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
instance = vk::createInstance({}, nullptr);
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance);
std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
assert(!physicalDevices.empty());
physicalDevice = physicalDevices[0];
const float defaultQueuePriority = 0.0f;
vk::DeviceQueueCreateInfo queueCreatInfo;
queueCreatInfo.queueFamilyIndex = queueFamilyIndex;
queueCreatInfo.queueCount = 1;
queueCreatInfo.pQueuePriorities = &defaultQueuePriority;
vk::DeviceCreateInfo deviceCreateInfo;
deviceCreateInfo.queueCreateInfoCount = 1;
deviceCreateInfo.pQueueCreateInfos = &queueCreatInfo;
device = physicalDevice.createDevice(deviceCreateInfo, nullptr);
queue = device.getQueue(queueFamilyIndex, 0);
}
// Copyright 2021 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef VULKAN_BENCHMARK_HPP_
#define VULKAN_BENCHMARK_HPP_
#include "VulkanHeaders.hpp"
class VulkanBenchmark
{
public:
VulkanBenchmark() = default;
virtual ~VulkanBenchmark();
// Call once after construction so that virtual functions may be called during init
void initialize();
private:
std::unique_ptr<vk::DynamicLoader> dl;
protected:
const uint32_t queueFamilyIndex = 0;
vk::Instance instance; // Owning handle
vk::PhysicalDevice physicalDevice;
vk::Device device; // Owning handle
vk::Queue queue;
};
#endif // VULKAN_BENCHMARK_HPP_
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