VulkanBenchmarks: factor out code into separate files
* Move utility classes into separate hpp/cpp files
* Move utility functions into Util.hpp/cpp
Bug: b/176981107
Change-Id: If9046f12080f1eb09378586673d871867a836a1b
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/51868
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
diff --git a/tests/VulkanBenchmarks/Buffer.cpp b/tests/VulkanBenchmarks/Buffer.cpp
new file mode 100644
index 0000000..93e6b0e
--- /dev/null
+++ b/tests/VulkanBenchmarks/Buffer.cpp
@@ -0,0 +1,42 @@
+// 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 "Buffer.hpp"
+
+Buffer::Buffer(vk::Device device, vk::DeviceSize size, vk::BufferUsageFlags usage)
+ : device(device)
+ , size(size)
+{
+ vk::BufferCreateInfo bufferInfo{};
+ bufferInfo.size = size;
+ bufferInfo.usage = usage;
+ bufferInfo.sharingMode = vk::SharingMode::eExclusive;
+
+ buffer = device.createBuffer(bufferInfo);
+
+ auto memRequirements = device.getBufferMemoryRequirements(buffer);
+
+ vk::MemoryAllocateInfo allocInfo{};
+ allocInfo.allocationSize = memRequirements.size;
+ allocInfo.memoryTypeIndex = 0; //TODO: getMemoryTypeIndex(memRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
+
+ bufferMemory = device.allocateMemory(allocInfo);
+ device.bindBufferMemory(buffer, bufferMemory, 0);
+}
+
+Buffer::~Buffer()
+{
+ device.freeMemory(bufferMemory);
+ device.destroyBuffer(buffer);
+}
diff --git a/tests/VulkanBenchmarks/Buffer.hpp b/tests/VulkanBenchmarks/Buffer.hpp
new file mode 100644
index 0000000..7db4eaf
--- /dev/null
+++ b/tests/VulkanBenchmarks/Buffer.hpp
@@ -0,0 +1,48 @@
+// 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 BENCHMARKS_BUFFER_HPP_
+#define BENCHMARKS_BUFFER_HPP_
+
+#include "VulkanHeaders.hpp"
+
+class Buffer
+{
+public:
+ Buffer(vk::Device device, vk::DeviceSize size, vk::BufferUsageFlags usage);
+ ~Buffer();
+
+ vk::Buffer getBuffer()
+ {
+ return buffer;
+ }
+
+ void *mapMemory()
+ {
+ return device.mapMemory(bufferMemory, 0, size);
+ }
+
+ void unmapMemory()
+ {
+ device.unmapMemory(bufferMemory);
+ }
+
+private:
+ const vk::Device device;
+ vk::DeviceSize size;
+ vk::Buffer buffer; // Owning handle
+ vk::DeviceMemory bufferMemory; // Owning handle
+};
+
+#endif // BENCHMARKS_BUFFER_HPP_
diff --git a/tests/VulkanBenchmarks/CMakeLists.txt b/tests/VulkanBenchmarks/CMakeLists.txt
index 3585067..ca7708e 100644
--- a/tests/VulkanBenchmarks/CMakeLists.txt
+++ b/tests/VulkanBenchmarks/CMakeLists.txt
@@ -22,8 +22,22 @@
)
set(VULKAN_BENCHMARKS_SRC_FILES
- VulkanBenchmarks.cpp
+ Buffer.cpp
+ Buffer.hpp
+ Framebuffer.cpp
+ Framebuffer.hpp
+ Image.cpp
+ Image.hpp
main.cpp
+ Swapchain.cpp
+ Swapchain.hpp
+ Util.cpp
+ Util.hpp
+ VulkanBenchmarks.cpp
+ VulkanHeaders.cpp
+ VulkanHeaders.hpp
+ Window.cpp
+ Window.hpp
)
add_executable(VulkanBenchmarks
diff --git a/tests/VulkanBenchmarks/Framebuffer.cpp b/tests/VulkanBenchmarks/Framebuffer.cpp
new file mode 100644
index 0000000..ab62a10
--- /dev/null
+++ b/tests/VulkanBenchmarks/Framebuffer.cpp
@@ -0,0 +1,51 @@
+// 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 "Framebuffer.hpp"
+
+Framebuffer::Framebuffer(vk::Device device, vk::ImageView attachment, vk::Format colorFormat, vk::RenderPass renderPass, vk::Extent2D extent, bool multisample)
+ : device(device)
+{
+ std::vector<vk::ImageView> attachments(multisample ? 2 : 1);
+
+ if(multisample)
+ {
+ multisampleImage.reset(new Image(device, extent.width, extent.height, colorFormat, vk::SampleCountFlagBits::e4));
+
+ // We'll be rendering to attachment location 0
+ attachments[0] = multisampleImage->getImageView();
+ attachments[1] = attachment; // Resolve attachment
+ }
+ else
+ {
+ attachments[0] = attachment;
+ }
+
+ vk::FramebufferCreateInfo framebufferCreateInfo;
+
+ framebufferCreateInfo.renderPass = renderPass;
+ framebufferCreateInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
+ framebufferCreateInfo.pAttachments = attachments.data();
+ framebufferCreateInfo.width = extent.width;
+ framebufferCreateInfo.height = extent.height;
+ framebufferCreateInfo.layers = 1;
+
+ framebuffer = device.createFramebuffer(framebufferCreateInfo);
+}
+
+Framebuffer::~Framebuffer()
+{
+ multisampleImage.reset();
+ device.destroyFramebuffer(framebuffer);
+}
diff --git a/tests/VulkanBenchmarks/Framebuffer.hpp b/tests/VulkanBenchmarks/Framebuffer.hpp
new file mode 100644
index 0000000..b3d1620
--- /dev/null
+++ b/tests/VulkanBenchmarks/Framebuffer.hpp
@@ -0,0 +1,38 @@
+// 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 BENCHMARKS_FRAMEBUFFER_HPP_
+#define BENCHMARKS_FRAMEBUFFER_HPP_
+
+#include "Image.hpp"
+#include "VulkanHeaders.hpp"
+
+class Framebuffer
+{
+public:
+ Framebuffer(vk::Device device, vk::ImageView attachment, vk::Format colorFormat, vk::RenderPass renderPass, vk::Extent2D extent, bool multisample);
+ ~Framebuffer();
+
+ vk::Framebuffer getFramebuffer()
+ {
+ return framebuffer;
+ }
+
+private:
+ const vk::Device device;
+ vk::Framebuffer framebuffer; // Owning handle
+ std::unique_ptr<Image> multisampleImage;
+};
+
+#endif // BENCHMARKS_FRAMEBUFFER_HPP_
diff --git a/tests/VulkanBenchmarks/Image.cpp b/tests/VulkanBenchmarks/Image.cpp
new file mode 100644
index 0000000..0ffc69b
--- /dev/null
+++ b/tests/VulkanBenchmarks/Image.cpp
@@ -0,0 +1,61 @@
+// 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 "Image.hpp"
+
+Image::Image(vk::Device device, uint32_t width, uint32_t height, vk::Format format, vk::SampleCountFlagBits sampleCount /*= vk::SampleCountFlagBits::e1*/)
+ : device(device)
+{
+ vk::ImageCreateInfo imageInfo;
+ imageInfo.imageType = vk::ImageType::e2D;
+ imageInfo.format = format;
+ imageInfo.tiling = vk::ImageTiling::eOptimal;
+ imageInfo.initialLayout = vk::ImageLayout::eGeneral;
+ imageInfo.usage = vk::ImageUsageFlagBits::eColorAttachment;
+ imageInfo.samples = sampleCount;
+ imageInfo.extent = vk::Extent3D(width, height, 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; //getMemoryTypeIndex(memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eDeviceLocal);
+
+ imageMemory = device.allocateMemory(allocateInfo);
+
+ device.bindImageMemory(image, imageMemory, 0);
+
+ vk::ImageViewCreateInfo imageViewInfo;
+ imageViewInfo.image = image;
+ imageViewInfo.viewType = vk::ImageViewType::e2D;
+ imageViewInfo.format = format;
+ imageViewInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
+ imageViewInfo.subresourceRange.baseMipLevel = 0;
+ imageViewInfo.subresourceRange.levelCount = 1;
+ imageViewInfo.subresourceRange.baseArrayLayer = 0;
+ imageViewInfo.subresourceRange.layerCount = 1;
+
+ imageView = device.createImageView(imageViewInfo);
+}
+
+Image::~Image()
+{
+ device.destroyImageView(imageView);
+ device.freeMemory(imageMemory);
+ device.destroyImage(image);
+}
diff --git a/tests/VulkanBenchmarks/Image.hpp b/tests/VulkanBenchmarks/Image.hpp
new file mode 100644
index 0000000..3526ff2
--- /dev/null
+++ b/tests/VulkanBenchmarks/Image.hpp
@@ -0,0 +1,44 @@
+// 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 BENCHMARKS_IMAGE_HPP_
+#define BENCHMARKS_IMAGE_HPP_
+
+#include "VulkanHeaders.hpp"
+
+class Image
+{
+public:
+ Image(vk::Device device, uint32_t width, uint32_t height, vk::Format format, vk::SampleCountFlagBits sampleCount = vk::SampleCountFlagBits::e1);
+ ~Image();
+
+ vk::Image getImage()
+ {
+ return image;
+ }
+
+ vk::ImageView getImageView()
+ {
+ return imageView;
+ }
+
+private:
+ const vk::Device device;
+
+ vk::Image image; // Owning handle
+ vk::DeviceMemory imageMemory; // Owning handle
+ vk::ImageView imageView; // Owning handle
+};
+
+#endif // BENCHMARKS_IMAGE_HPP_
diff --git a/tests/VulkanBenchmarks/Swapchain.cpp b/tests/VulkanBenchmarks/Swapchain.cpp
new file mode 100644
index 0000000..843fc63
--- /dev/null
+++ b/tests/VulkanBenchmarks/Swapchain.cpp
@@ -0,0 +1,89 @@
+// 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 "Swapchain.hpp"
+#include "Window.hpp"
+
+Swapchain::Swapchain(vk::PhysicalDevice physicalDevice, vk::Device device, Window &window)
+ : device(device)
+{
+ vk::SurfaceKHR surface = window.getSurface();
+
+ // Create the swapchain
+ vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface);
+ extent = surfaceCapabilities.currentExtent;
+
+ vk::SwapchainCreateInfoKHR swapchainCreateInfo;
+ swapchainCreateInfo.surface = surface;
+ swapchainCreateInfo.minImageCount = 2; // double-buffered
+ swapchainCreateInfo.imageFormat = colorFormat;
+ swapchainCreateInfo.imageColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear;
+ swapchainCreateInfo.imageExtent = extent;
+ swapchainCreateInfo.imageUsage = vk::ImageUsageFlagBits::eColorAttachment;
+ swapchainCreateInfo.preTransform = vk::SurfaceTransformFlagBitsKHR::eIdentity;
+ swapchainCreateInfo.imageArrayLayers = 1;
+ swapchainCreateInfo.imageSharingMode = vk::SharingMode::eExclusive;
+ swapchainCreateInfo.presentMode = vk::PresentModeKHR::eFifo;
+ swapchainCreateInfo.clipped = VK_TRUE;
+ swapchainCreateInfo.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
+
+ swapchain = device.createSwapchainKHR(swapchainCreateInfo);
+
+ // Obtain the images and create views for them
+ images = device.getSwapchainImagesKHR(swapchain);
+
+ imageViews.resize(images.size());
+ for(size_t i = 0; i < imageViews.size(); i++)
+ {
+ vk::ImageViewCreateInfo colorAttachmentView;
+ colorAttachmentView.image = images[i];
+ colorAttachmentView.viewType = vk::ImageViewType::e2D;
+ colorAttachmentView.format = colorFormat;
+ colorAttachmentView.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
+ colorAttachmentView.subresourceRange.baseMipLevel = 0;
+ colorAttachmentView.subresourceRange.levelCount = 1;
+ colorAttachmentView.subresourceRange.baseArrayLayer = 0;
+ colorAttachmentView.subresourceRange.layerCount = 1;
+
+ imageViews[i] = device.createImageView(colorAttachmentView);
+ }
+}
+
+Swapchain::~Swapchain()
+{
+ for(auto &imageView : imageViews)
+ {
+ device.destroyImageView(imageView, nullptr);
+ }
+
+ device.destroySwapchainKHR(swapchain, nullptr);
+}
+
+void Swapchain::acquireNextImage(VkSemaphore presentCompleteSemaphore, uint32_t &imageIndex)
+{
+ auto result = device.acquireNextImageKHR(swapchain, UINT64_MAX, presentCompleteSemaphore, vk::Fence());
+ imageIndex = result.value;
+}
+
+void Swapchain::queuePresent(vk::Queue queue, uint32_t imageIndex, vk::Semaphore waitSemaphore)
+{
+ vk::PresentInfoKHR presentInfo;
+ presentInfo.pWaitSemaphores = &waitSemaphore;
+ presentInfo.waitSemaphoreCount = 1;
+ presentInfo.swapchainCount = 1;
+ presentInfo.pSwapchains = &swapchain;
+ presentInfo.pImageIndices = &imageIndex;
+
+ queue.presentKHR(presentInfo);
+}
diff --git a/tests/VulkanBenchmarks/Swapchain.hpp b/tests/VulkanBenchmarks/Swapchain.hpp
new file mode 100644
index 0000000..d7ab6fc
--- /dev/null
+++ b/tests/VulkanBenchmarks/Swapchain.hpp
@@ -0,0 +1,59 @@
+// 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 BENCHMARKS_SWAPCHAIN_HPP_
+#define BENCHMARKS_SWAPCHAIN_HPP_
+
+#include "VulkanHeaders.hpp"
+#include <vector>
+
+class Window;
+
+class Swapchain
+{
+public:
+ Swapchain(vk::PhysicalDevice physicalDevice, vk::Device device, Window &window);
+ ~Swapchain();
+
+ void acquireNextImage(VkSemaphore presentCompleteSemaphore, uint32_t &imageIndex);
+ void queuePresent(vk::Queue queue, uint32_t imageIndex, vk::Semaphore waitSemaphore);
+
+ size_t imageCount() const
+ {
+ return images.size();
+ }
+
+ vk::ImageView getImageView(size_t i) const
+ {
+ return imageViews[i];
+ }
+
+ vk::Extent2D getExtent() const
+ {
+ return extent;
+ }
+
+ const vk::Format colorFormat = vk::Format::eB8G8R8A8Unorm;
+
+private:
+ const vk::Device device;
+
+ vk::SwapchainKHR swapchain; // Owning handle
+ vk::Extent2D extent;
+
+ std::vector<vk::Image> images; // Weak pointers. Presentable images owned by swapchain object.
+ std::vector<vk::ImageView> imageViews; // Owning handles
+};
+
+#endif // BENCHMARKS_SWAPCHAIN_HPP_
diff --git a/tests/VulkanBenchmarks/Util.cpp b/tests/VulkanBenchmarks/Util.cpp
new file mode 100644
index 0000000..af2980c
--- /dev/null
+++ b/tests/VulkanBenchmarks/Util.cpp
@@ -0,0 +1,174 @@
+// 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 "Util.hpp"
+#include "SPIRV/GlslangToSpv.h"
+#include "StandAlone/ResourceLimits.h"
+
+namespace Util {
+
+uint32_t getMemoryTypeIndex(vk::PhysicalDevice physicalDevice, uint32_t typeBits, vk::MemoryPropertyFlags properties)
+{
+ vk::PhysicalDeviceMemoryProperties deviceMemoryProperties = physicalDevice.getMemoryProperties();
+ for(uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++)
+ {
+ if((typeBits & 1) == 1)
+ {
+ if((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
+ {
+ return i;
+ }
+ }
+ typeBits >>= 1;
+ }
+
+ assert(false);
+ return -1;
+}
+
+vk::CommandBuffer beginSingleTimeCommands(vk::Device device, vk::CommandPool commandPool)
+{
+ vk::CommandBufferAllocateInfo allocInfo{};
+ allocInfo.level = vk::CommandBufferLevel::ePrimary;
+ allocInfo.commandPool = commandPool;
+ allocInfo.commandBufferCount = 1;
+
+ auto commandBuffer = device.allocateCommandBuffers(allocInfo);
+
+ vk::CommandBufferBeginInfo beginInfo{};
+ beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
+
+ commandBuffer[0].begin(beginInfo);
+
+ return commandBuffer[0];
+}
+
+void endSingleTimeCommands(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::CommandBuffer commandBuffer)
+{
+ commandBuffer.end();
+
+ vk::SubmitInfo submitInfo{};
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &commandBuffer;
+
+ vk::Fence fence = {}; // TODO: pass in fence?
+ queue.submit(1, &submitInfo, fence);
+ queue.waitIdle();
+
+ device.freeCommandBuffers(commandPool, 1, &commandBuffer);
+}
+
+void transitionImageLayout(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::Image image, vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout)
+{
+ vk::CommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool);
+
+ vk::ImageMemoryBarrier barrier{};
+ barrier.oldLayout = oldLayout;
+ barrier.newLayout = newLayout;
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.image = image;
+ barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
+ barrier.subresourceRange.baseMipLevel = 0;
+ barrier.subresourceRange.levelCount = 1;
+ barrier.subresourceRange.baseArrayLayer = 0;
+ barrier.subresourceRange.layerCount = 1;
+
+ vk::PipelineStageFlags sourceStage;
+ vk::PipelineStageFlags destinationStage;
+
+ if(oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal)
+ {
+ barrier.srcAccessMask = {};
+ barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
+
+ sourceStage = vk::PipelineStageFlagBits::eTopOfPipe;
+ destinationStage = vk::PipelineStageFlagBits::eTransfer;
+ }
+ else if(oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal)
+ {
+ barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
+ barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead;
+
+ sourceStage = vk::PipelineStageFlagBits::eTransfer;
+ destinationStage = vk::PipelineStageFlagBits::eFragmentShader;
+ }
+ else
+ {
+ assert(!"unsupported layout transition!");
+ }
+
+ commandBuffer.pipelineBarrier(sourceStage, destinationStage, vk::DependencyFlags{}, 0, nullptr, 0, nullptr, 1, &barrier);
+
+ endSingleTimeCommands(device, commandPool, queue, commandBuffer);
+}
+
+void copyBufferToImage(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::Buffer buffer, vk::Image image, uint32_t width, uint32_t height)
+{
+ vk::CommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool);
+
+ vk::BufferImageCopy region{};
+ region.bufferOffset = 0;
+ region.bufferRowLength = 0;
+ region.bufferImageHeight = 0;
+ region.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
+ region.imageSubresource.mipLevel = 0;
+ region.imageSubresource.baseArrayLayer = 0;
+ region.imageSubresource.layerCount = 1;
+ region.imageOffset = vk::Offset3D{ 0, 0, 0 };
+ region.imageExtent = vk::Extent3D{ width, height, 1 };
+
+ commandBuffer.copyBufferToImage(buffer, image, vk::ImageLayout::eTransferDstOptimal, 1, ®ion);
+
+ endSingleTimeCommands(device, commandPool, queue, commandBuffer);
+}
+
+std::vector<uint32_t> compileGLSLtoSPIRV(const char *glslSource, EShLanguage glslLanguage)
+{
+ // glslang requires one-time initialization.
+ const struct GlslangProcessInitialiser
+ {
+ GlslangProcessInitialiser() { glslang::InitializeProcess(); }
+ ~GlslangProcessInitialiser() { glslang::FinalizeProcess(); }
+ } glslangInitialiser;
+
+ std::unique_ptr<glslang::TShader> glslangShader = std::make_unique<glslang::TShader>(glslLanguage);
+
+ glslangShader->setStrings(&glslSource, 1);
+ glslangShader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
+ glslangShader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3);
+
+ const int defaultVersion = 100;
+ EShMessages messages = static_cast<EShMessages>(EShMessages::EShMsgDefault | EShMessages::EShMsgSpvRules | EShMessages::EShMsgVulkanRules);
+ bool parseResult = glslangShader->parse(&glslang::DefaultTBuiltInResource, defaultVersion, false, messages);
+
+ if(!parseResult)
+ {
+ std::string debugLog = glslangShader->getInfoDebugLog();
+ std::string infoLog = glslangShader->getInfoLog();
+ assert(false);
+ }
+
+ glslang::TIntermediate *intermediateRepresentation = glslangShader->getIntermediate();
+ assert(intermediateRepresentation);
+
+ std::vector<uint32_t> spirv;
+ glslang::SpvOptions options;
+ glslang::GlslangToSpv(*intermediateRepresentation, spirv, &options);
+ assert(spirv.size() != 0);
+
+ return spirv;
+}
+
+} // namespace Util
diff --git a/tests/VulkanBenchmarks/Util.hpp b/tests/VulkanBenchmarks/Util.hpp
new file mode 100644
index 0000000..adfdedb
--- /dev/null
+++ b/tests/VulkanBenchmarks/Util.hpp
@@ -0,0 +1,39 @@
+// 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 BENCHMARKS_UTIL_HPP_
+#define BENCHMARKS_UTIL_HPP_
+
+#include "VulkanHeaders.hpp"
+#include "glslang/Public/ShaderLang.h"
+
+#include <vector>
+
+namespace Util {
+
+uint32_t getMemoryTypeIndex(vk::PhysicalDevice physicalDevice, uint32_t typeBits, vk::MemoryPropertyFlags properties);
+
+vk::CommandBuffer beginSingleTimeCommands(vk::Device device, vk::CommandPool commandPool);
+
+void endSingleTimeCommands(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::CommandBuffer commandBuffer);
+
+void transitionImageLayout(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::Image image, vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout);
+
+void copyBufferToImage(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::Buffer buffer, vk::Image image, uint32_t width, uint32_t height);
+
+std::vector<uint32_t> compileGLSLtoSPIRV(const char *glslSource, EShLanguage glslLanguage);
+
+} // namespace Util
+
+#endif // BENCHMARKS_UTIL_HPP_
diff --git a/tests/VulkanBenchmarks/VulkanBenchmarks.cpp b/tests/VulkanBenchmarks/VulkanBenchmarks.cpp
index 2f566ce..9196dd9 100644
--- a/tests/VulkanBenchmarks/VulkanBenchmarks.cpp
+++ b/tests/VulkanBenchmarks/VulkanBenchmarks.cpp
@@ -14,157 +14,19 @@
#include "benchmark/benchmark.h"
-#if !defined(USE_HEADLESS_SURFACE)
-# define USE_HEADLESS_SURFACE 0
-#endif
-
-#if !defined(_WIN32)
-// @TODO: implement native Window support for current platform. For now, always use HeadlessSurface.
-# undef USE_HEADLESS_SURFACE
-# define USE_HEADLESS_SURFACE 1
-#endif
-
-#if defined(_WIN32)
-# define VK_USE_PLATFORM_WIN32_KHR
-#endif
-#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
-#define VULKAN_HPP_NO_NODISCARD_WARNINGS
-#include <vulkan/vulkan.hpp>
-VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
-
-#include "SPIRV/GlslangToSpv.h"
-#include "StandAlone/ResourceLimits.h"
-#include "glslang/Public/ShaderLang.h"
-
-#if defined(_WIN32)
-# define WIN32_LEAN_AND_MEAN
-# include <Windows.h>
-#endif
+#include "Buffer.hpp"
+#include "Framebuffer.hpp"
+#include "Image.hpp"
+#include "Swapchain.hpp"
+#include "Util.hpp"
+#include "VulkanHeaders.hpp"
+#include "Window.hpp"
#include <cassert>
#include <vector>
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
-namespace {
-uint32_t getMemoryTypeIndex(vk::PhysicalDevice physicalDevice, uint32_t typeBits, vk::MemoryPropertyFlags properties)
-{
- vk::PhysicalDeviceMemoryProperties deviceMemoryProperties = physicalDevice.getMemoryProperties();
- for(uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++)
- {
- if((typeBits & 1) == 1)
- {
- if((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
- {
- return i;
- }
- }
- typeBits >>= 1;
- }
-
- assert(false);
- return -1;
-}
-
-vk::CommandBuffer beginSingleTimeCommands(vk::Device device, vk::CommandPool commandPool)
-{
- vk::CommandBufferAllocateInfo allocInfo{};
- allocInfo.level = vk::CommandBufferLevel::ePrimary;
- allocInfo.commandPool = commandPool;
- allocInfo.commandBufferCount = 1;
-
- auto commandBuffer = device.allocateCommandBuffers(allocInfo);
-
- vk::CommandBufferBeginInfo beginInfo{};
- beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
-
- commandBuffer[0].begin(beginInfo);
-
- return commandBuffer[0];
-}
-
-void endSingleTimeCommands(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::CommandBuffer commandBuffer)
-{
- commandBuffer.end();
-
- vk::SubmitInfo submitInfo{};
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &commandBuffer;
-
- vk::Fence fence = {}; // TODO: pass in fence?
- queue.submit(1, &submitInfo, fence);
- queue.waitIdle();
-
- device.freeCommandBuffers(commandPool, 1, &commandBuffer);
-}
-
-void transitionImageLayout(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::Image image, vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout)
-{
- vk::CommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool);
-
- vk::ImageMemoryBarrier barrier{};
- barrier.oldLayout = oldLayout;
- barrier.newLayout = newLayout;
- barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.image = image;
- barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
- barrier.subresourceRange.baseMipLevel = 0;
- barrier.subresourceRange.levelCount = 1;
- barrier.subresourceRange.baseArrayLayer = 0;
- barrier.subresourceRange.layerCount = 1;
-
- vk::PipelineStageFlags sourceStage;
- vk::PipelineStageFlags destinationStage;
-
- if(oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal)
- {
- barrier.srcAccessMask = {};
- barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
-
- sourceStage = vk::PipelineStageFlagBits::eTopOfPipe;
- destinationStage = vk::PipelineStageFlagBits::eTransfer;
- }
- else if(oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal)
- {
- barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
- barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead;
-
- sourceStage = vk::PipelineStageFlagBits::eTransfer;
- destinationStage = vk::PipelineStageFlagBits::eFragmentShader;
- }
- else
- {
- assert(!"unsupported layout transition!");
- }
-
- commandBuffer.pipelineBarrier(sourceStage, destinationStage, vk::DependencyFlags{}, 0, nullptr, 0, nullptr, 1, &barrier);
-
- endSingleTimeCommands(device, commandPool, queue, commandBuffer);
-}
-
-void copyBufferToImage(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::Buffer buffer, vk::Image image, uint32_t width, uint32_t height)
-{
- vk::CommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool);
-
- vk::BufferImageCopy region{};
- region.bufferOffset = 0;
- region.bufferRowLength = 0;
- region.bufferImageHeight = 0;
- region.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
- region.imageSubresource.mipLevel = 0;
- region.imageSubresource.baseArrayLayer = 0;
- region.imageSubresource.layerCount = 1;
- region.imageOffset = vk::Offset3D{ 0, 0, 0 };
- region.imageExtent = vk::Extent3D{ width, height, 1 };
-
- commandBuffer.copyBufferToImage(buffer, image, vk::ImageLayout::eTransferDstOptimal, 1, ®ion);
-
- endSingleTimeCommands(device, commandPool, queue, commandBuffer);
-}
-
-} // namespace
-
class VulkanBenchmark
{
public:
@@ -337,424 +199,6 @@
}
}
-#if USE_HEADLESS_SURFACE
-class Window
-{
-public:
- Window(vk::Instance instance, vk::Extent2D windowSize)
- {
- vk::HeadlessSurfaceCreateInfoEXT surfaceCreateInfo;
- surface = instance.createHeadlessSurfaceEXT(surfaceCreateInfo);
- assert(surface);
- }
-
- ~Window()
- {
- instance.destroySurfaceKHR(surface, nullptr);
- }
-
- vk::SurfaceKHR getSurface()
- {
- return surface;
- }
-
- void show()
- {
- }
-
-private:
- const vk::Instance instance;
- vk::SurfaceKHR surface;
-};
-#elif defined(_WIN32)
-class Window
-{
-public:
- Window(vk::Instance instance, vk::Extent2D windowSize)
- {
- windowClass.cbSize = sizeof(WNDCLASSEX);
- windowClass.style = CS_HREDRAW | CS_VREDRAW;
- windowClass.lpfnWndProc = DefWindowProc;
- windowClass.cbClsExtra = 0;
- windowClass.cbWndExtra = 0;
- windowClass.hInstance = moduleInstance;
- windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
- windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
- windowClass.lpszMenuName = NULL;
- windowClass.lpszClassName = "Window";
- windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
-
- RegisterClassEx(&windowClass);
-
- DWORD style = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
- DWORD extendedStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
-
- RECT windowRect;
- windowRect.left = 0L;
- windowRect.top = 0L;
- windowRect.right = (long)windowSize.width;
- windowRect.bottom = (long)windowSize.height;
-
- AdjustWindowRectEx(&windowRect, style, FALSE, extendedStyle);
- uint32_t x = (GetSystemMetrics(SM_CXSCREEN) - windowRect.right) / 2;
- uint32_t y = (GetSystemMetrics(SM_CYSCREEN) - windowRect.bottom) / 2;
-
- window = CreateWindowEx(extendedStyle, "Window", "Hello",
- style | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
- x, y,
- windowRect.right - windowRect.left,
- windowRect.bottom - windowRect.top,
- NULL, NULL, moduleInstance, NULL);
-
- SetForegroundWindow(window);
- SetFocus(window);
-
- // Create the Vulkan surface
- vk::Win32SurfaceCreateInfoKHR surfaceCreateInfo;
- surfaceCreateInfo.hinstance = moduleInstance;
- surfaceCreateInfo.hwnd = window;
- surface = instance.createWin32SurfaceKHR(surfaceCreateInfo);
- assert(surface);
- }
-
- ~Window()
- {
- instance.destroySurfaceKHR(surface, nullptr);
- DestroyWindow(window);
- UnregisterClass("Window", moduleInstance);
- }
-
- vk::SurfaceKHR getSurface()
- {
- return surface;
- }
-
- void show()
- {
- ShowWindow(window, SW_SHOW);
- }
-
-private:
- HWND window;
- HINSTANCE moduleInstance;
- WNDCLASSEX windowClass;
- const vk::Instance instance;
- vk::SurfaceKHR surface;
-};
-#else
-# error Window class unimplemented for this platform
-#endif
-
-class Swapchain
-{
-public:
- Swapchain(vk::PhysicalDevice physicalDevice, vk::Device device, Window &window)
- : device(device)
- {
- vk::SurfaceKHR surface = window.getSurface();
-
- // Create the swapchain
- vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface);
- extent = surfaceCapabilities.currentExtent;
-
- vk::SwapchainCreateInfoKHR swapchainCreateInfo;
- swapchainCreateInfo.surface = surface;
- swapchainCreateInfo.minImageCount = 2; // double-buffered
- swapchainCreateInfo.imageFormat = colorFormat;
- swapchainCreateInfo.imageColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear;
- swapchainCreateInfo.imageExtent = extent;
- swapchainCreateInfo.imageUsage = vk::ImageUsageFlagBits::eColorAttachment;
- swapchainCreateInfo.preTransform = vk::SurfaceTransformFlagBitsKHR::eIdentity;
- swapchainCreateInfo.imageArrayLayers = 1;
- swapchainCreateInfo.imageSharingMode = vk::SharingMode::eExclusive;
- swapchainCreateInfo.presentMode = vk::PresentModeKHR::eFifo;
- swapchainCreateInfo.clipped = VK_TRUE;
- swapchainCreateInfo.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
-
- swapchain = device.createSwapchainKHR(swapchainCreateInfo);
-
- // Obtain the images and create views for them
- images = device.getSwapchainImagesKHR(swapchain);
-
- imageViews.resize(images.size());
- for(size_t i = 0; i < imageViews.size(); i++)
- {
- vk::ImageViewCreateInfo colorAttachmentView;
- colorAttachmentView.image = images[i];
- colorAttachmentView.viewType = vk::ImageViewType::e2D;
- colorAttachmentView.format = colorFormat;
- colorAttachmentView.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
- colorAttachmentView.subresourceRange.baseMipLevel = 0;
- colorAttachmentView.subresourceRange.levelCount = 1;
- colorAttachmentView.subresourceRange.baseArrayLayer = 0;
- colorAttachmentView.subresourceRange.layerCount = 1;
-
- imageViews[i] = device.createImageView(colorAttachmentView);
- }
- }
-
- ~Swapchain()
- {
- for(auto &imageView : imageViews)
- {
- device.destroyImageView(imageView, nullptr);
- }
-
- device.destroySwapchainKHR(swapchain, nullptr);
- }
-
- void acquireNextImage(VkSemaphore presentCompleteSemaphore, uint32_t &imageIndex)
- {
- auto result = device.acquireNextImageKHR(swapchain, UINT64_MAX, presentCompleteSemaphore, vk::Fence());
- imageIndex = result.value;
- }
-
- void queuePresent(vk::Queue queue, uint32_t imageIndex, vk::Semaphore waitSemaphore)
- {
- vk::PresentInfoKHR presentInfo;
- presentInfo.pWaitSemaphores = &waitSemaphore;
- presentInfo.waitSemaphoreCount = 1;
- presentInfo.swapchainCount = 1;
- presentInfo.pSwapchains = &swapchain;
- presentInfo.pImageIndices = &imageIndex;
-
- queue.presentKHR(presentInfo);
- }
-
- size_t imageCount() const
- {
- return images.size();
- }
-
- vk::ImageView getImageView(size_t i) const
- {
- return imageViews[i];
- }
-
- vk::Extent2D getExtent() const
- {
- return extent;
- }
-
- const vk::Format colorFormat = vk::Format::eB8G8R8A8Unorm;
-
-private:
- const vk::Device device;
-
- vk::SwapchainKHR swapchain; // Owning handle
- vk::Extent2D extent;
-
- std::vector<vk::Image> images; // Weak pointers. Presentable images owned by swapchain object.
- std::vector<vk::ImageView> imageViews; // Owning handles
-};
-
-class Buffer
-{
-public:
- Buffer(vk::Device device, vk::DeviceSize size, vk::BufferUsageFlags usage)
- : device(device)
- , size(size)
- {
- vk::BufferCreateInfo bufferInfo{};
- bufferInfo.size = size;
- bufferInfo.usage = usage;
- bufferInfo.sharingMode = vk::SharingMode::eExclusive;
-
- buffer = device.createBuffer(bufferInfo);
-
- auto memRequirements = device.getBufferMemoryRequirements(buffer);
-
- vk::MemoryAllocateInfo allocInfo{};
- allocInfo.allocationSize = memRequirements.size;
- allocInfo.memoryTypeIndex = 0; //TODO: getMemoryTypeIndex(memRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
-
- bufferMemory = device.allocateMemory(allocInfo);
- device.bindBufferMemory(buffer, bufferMemory, 0);
- }
-
- ~Buffer()
- {
- device.freeMemory(bufferMemory);
- device.destroyBuffer(buffer);
- }
-
- vk::Buffer getBuffer()
- {
- return buffer;
- }
-
- void *mapMemory()
- {
- return device.mapMemory(bufferMemory, 0, size);
- }
-
- void unmapMemory()
- {
- device.unmapMemory(bufferMemory);
- }
-
-private:
- const vk::Device device;
- vk::DeviceSize size;
- vk::Buffer buffer; // Owning handle
- vk::DeviceMemory bufferMemory; // Owning handle
-};
-
-class Image
-{
-public:
- Image(vk::Device device, uint32_t width, uint32_t height, vk::Format format, vk::SampleCountFlagBits sampleCount = vk::SampleCountFlagBits::e1)
- : device(device)
- {
- vk::ImageCreateInfo imageInfo;
- imageInfo.imageType = vk::ImageType::e2D;
- imageInfo.format = format;
- imageInfo.tiling = vk::ImageTiling::eOptimal;
- imageInfo.initialLayout = vk::ImageLayout::eGeneral;
- imageInfo.usage = vk::ImageUsageFlagBits::eColorAttachment;
- imageInfo.samples = sampleCount;
- imageInfo.extent = vk::Extent3D(width, height, 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; //getMemoryTypeIndex(memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eDeviceLocal);
-
- imageMemory = device.allocateMemory(allocateInfo);
-
- device.bindImageMemory(image, imageMemory, 0);
-
- vk::ImageViewCreateInfo imageViewInfo;
- imageViewInfo.image = image;
- imageViewInfo.viewType = vk::ImageViewType::e2D;
- imageViewInfo.format = format;
- imageViewInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
- imageViewInfo.subresourceRange.baseMipLevel = 0;
- imageViewInfo.subresourceRange.levelCount = 1;
- imageViewInfo.subresourceRange.baseArrayLayer = 0;
- imageViewInfo.subresourceRange.layerCount = 1;
-
- imageView = device.createImageView(imageViewInfo);
- }
-
- ~Image()
- {
- device.destroyImageView(imageView);
- device.freeMemory(imageMemory);
- device.destroyImage(image);
- }
-
- vk::Image getImage()
- {
- return image;
- }
-
- vk::ImageView getImageView()
- {
- return imageView;
- }
-
-private:
- const vk::Device device;
-
- vk::Image image; // Owning handle
- vk::DeviceMemory imageMemory; // Owning handle
- vk::ImageView imageView; // Owning handle
-};
-
-class Framebuffer
-{
-public:
- Framebuffer(vk::Device device, vk::ImageView attachment, vk::Format colorFormat, vk::RenderPass renderPass, vk::Extent2D extent, bool multisample)
- : device(device)
- {
- std::vector<vk::ImageView> attachments(multisample ? 2 : 1);
-
- if(multisample)
- {
- multisampleImage.reset(new Image(device, extent.width, extent.height, colorFormat, vk::SampleCountFlagBits::e4));
-
- // We'll be rendering to attachment location 0
- attachments[0] = multisampleImage->getImageView();
- attachments[1] = attachment; // Resolve attachment
- }
- else
- {
- attachments[0] = attachment;
- }
-
- vk::FramebufferCreateInfo framebufferCreateInfo;
-
- framebufferCreateInfo.renderPass = renderPass;
- framebufferCreateInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
- framebufferCreateInfo.pAttachments = attachments.data();
- framebufferCreateInfo.width = extent.width;
- framebufferCreateInfo.height = extent.height;
- framebufferCreateInfo.layers = 1;
-
- framebuffer = device.createFramebuffer(framebufferCreateInfo);
- }
-
- ~Framebuffer()
- {
- multisampleImage.reset();
- device.destroyFramebuffer(framebuffer);
- }
-
- vk::Framebuffer getFramebuffer()
- {
- return framebuffer;
- }
-
-private:
- const vk::Device device;
- vk::Framebuffer framebuffer; // Owning handle
- std::unique_ptr<Image> multisampleImage;
-};
-
-static std::vector<uint32_t> compileGLSLtoSPIRV(const char *glslSource, EShLanguage glslLanguage)
-{
- // glslang requires one-time initialization.
- const struct GlslangProcessInitialiser
- {
- GlslangProcessInitialiser() { glslang::InitializeProcess(); }
- ~GlslangProcessInitialiser() { glslang::FinalizeProcess(); }
- } glslangInitialiser;
-
- std::unique_ptr<glslang::TShader> glslangShader = std::make_unique<glslang::TShader>(glslLanguage);
-
- glslangShader->setStrings(&glslSource, 1);
- glslangShader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
- glslangShader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3);
-
- const int defaultVersion = 100;
- EShMessages messages = static_cast<EShMessages>(EShMessages::EShMsgDefault | EShMessages::EShMsgSpvRules | EShMessages::EShMsgVulkanRules);
- bool parseResult = glslangShader->parse(&glslang::DefaultTBuiltInResource, defaultVersion, false, messages);
-
- if(!parseResult)
- {
- std::string debugLog = glslangShader->getInfoDebugLog();
- std::string infoLog = glslangShader->getInfoLog();
- assert(false);
- }
-
- glslang::TIntermediate *intermediateRepresentation = glslangShader->getIntermediate();
- assert(intermediateRepresentation);
-
- std::vector<uint32_t> spirv;
- glslang::SpvOptions options;
- glslang::GlslangToSpv(*intermediateRepresentation, spirv, &options);
- assert(spirv.size() != 0);
-
- return spirv;
-}
-
class TriangleBenchmark : public VulkanBenchmark
{
public:
@@ -871,9 +315,9 @@
memset(data, 255, bufferSize);
buffer.unmapMemory();
- transitionImageLayout(device, commandPool, queue, texture->getImage(), vk::Format::eR8G8B8A8Unorm, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal);
- copyBufferToImage(device, commandPool, queue, buffer.getBuffer(), texture->getImage(), 16, 16);
- transitionImageLayout(device, commandPool, queue, texture->getImage(), vk::Format::eR8G8B8A8Unorm, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal);
+ Util::transitionImageLayout(device, commandPool, queue, texture->getImage(), vk::Format::eR8G8B8A8Unorm, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal);
+ Util::copyBufferToImage(device, commandPool, queue, buffer.getBuffer(), texture->getImage(), 16, 16);
+ Util::transitionImageLayout(device, commandPool, queue, texture->getImage(), vk::Format::eR8G8B8A8Unorm, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal);
vk::SamplerCreateInfo samplerInfo;
samplerInfo.magFilter = vk::Filter::eLinear;
@@ -993,7 +437,7 @@
vk::MemoryAllocateInfo memoryAllocateInfo;
vk::MemoryRequirements memoryRequirements = device.getBufferMemoryRequirements(vertices.buffer);
memoryAllocateInfo.allocationSize = memoryRequirements.size;
- memoryAllocateInfo.memoryTypeIndex = getMemoryTypeIndex(physicalDevice, memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
+ memoryAllocateInfo.memoryTypeIndex = Util::getMemoryTypeIndex(physicalDevice, memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
vertices.memory = device.allocateMemory(memoryAllocateInfo);
void *data = device.mapMemory(vertices.memory, 0, VK_WHOLE_SIZE);
@@ -1108,7 +552,7 @@
vk::ShaderModule createShaderModule(const char *glslSource, EShLanguage glslLanguage)
{
- auto spirv = compileGLSLtoSPIRV(glslSource, glslLanguage);
+ auto spirv = Util::compileGLSLtoSPIRV(glslSource, glslLanguage);
vk::ShaderModuleCreateInfo moduleCreateInfo;
moduleCreateInfo.codeSize = spirv.size() * sizeof(uint32_t);
diff --git a/tests/VulkanBenchmarks/VulkanHeaders.cpp b/tests/VulkanBenchmarks/VulkanHeaders.cpp
new file mode 100644
index 0000000..e8750df
--- /dev/null
+++ b/tests/VulkanBenchmarks/VulkanHeaders.cpp
@@ -0,0 +1,3 @@
+#include "VulkanHeaders.hpp"
+
+VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
diff --git a/tests/VulkanBenchmarks/VulkanHeaders.hpp b/tests/VulkanBenchmarks/VulkanHeaders.hpp
new file mode 100644
index 0000000..69d79f1
--- /dev/null
+++ b/tests/VulkanBenchmarks/VulkanHeaders.hpp
@@ -0,0 +1,35 @@
+// 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 BENCHMARKS_VULKAN_HEADERS_HPP_
+#define BENCHMARKS_VULKAN_HEADERS_HPP_
+
+#if !defined(USE_HEADLESS_SURFACE)
+# define USE_HEADLESS_SURFACE 0
+#endif
+
+#if !defined(_WIN32)
+// @TODO: implement native Window support for current platform. For now, always use HeadlessSurface.
+# undef USE_HEADLESS_SURFACE
+# define USE_HEADLESS_SURFACE 1
+#endif
+
+#if defined(_WIN32)
+# define VK_USE_PLATFORM_WIN32_KHR
+#endif
+#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
+#define VULKAN_HPP_NO_NODISCARD_WARNINGS
+#include <vulkan/vulkan.hpp>
+
+#endif // BENCHMARKS_VULKAN_HEADERS_HPP_
diff --git a/tests/VulkanBenchmarks/Window.cpp b/tests/VulkanBenchmarks/Window.cpp
new file mode 100644
index 0000000..1cfdbe6
--- /dev/null
+++ b/tests/VulkanBenchmarks/Window.cpp
@@ -0,0 +1,109 @@
+// 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 "Window.hpp"
+
+#if USE_HEADLESS_SURFACE
+
+Window::Window(vk::Instance instance, vk::Extent2D windowSize)
+{
+ vk::HeadlessSurfaceCreateInfoEXT surfaceCreateInfo;
+ surface = instance.createHeadlessSurfaceEXT(surfaceCreateInfo);
+ assert(surface);
+}
+
+Window::~Window()
+{
+ instance.destroySurfaceKHR(surface, nullptr);
+}
+
+vk::SurfaceKHR Window::getSurface()
+{
+ return surface;
+}
+
+void Window::show()
+{
+}
+
+#elif defined(_WIN32)
+
+Window::Window(vk::Instance instance, vk::Extent2D windowSize)
+{
+ windowClass.cbSize = sizeof(WNDCLASSEX);
+ windowClass.style = CS_HREDRAW | CS_VREDRAW;
+ windowClass.lpfnWndProc = DefWindowProc;
+ windowClass.cbClsExtra = 0;
+ windowClass.cbWndExtra = 0;
+ windowClass.hInstance = moduleInstance;
+ windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ windowClass.lpszMenuName = NULL;
+ windowClass.lpszClassName = "Window";
+ windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
+
+ RegisterClassEx(&windowClass);
+
+ DWORD style = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+ DWORD extendedStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
+
+ RECT windowRect;
+ windowRect.left = 0L;
+ windowRect.top = 0L;
+ windowRect.right = (long)windowSize.width;
+ windowRect.bottom = (long)windowSize.height;
+
+ AdjustWindowRectEx(&windowRect, style, FALSE, extendedStyle);
+ uint32_t x = (GetSystemMetrics(SM_CXSCREEN) - windowRect.right) / 2;
+ uint32_t y = (GetSystemMetrics(SM_CYSCREEN) - windowRect.bottom) / 2;
+
+ window = CreateWindowEx(extendedStyle, "Window", "Hello",
+ style | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+ x, y,
+ windowRect.right - windowRect.left,
+ windowRect.bottom - windowRect.top,
+ NULL, NULL, moduleInstance, NULL);
+
+ SetForegroundWindow(window);
+ SetFocus(window);
+
+ // Create the Vulkan surface
+ vk::Win32SurfaceCreateInfoKHR surfaceCreateInfo;
+ surfaceCreateInfo.hinstance = moduleInstance;
+ surfaceCreateInfo.hwnd = window;
+ surface = instance.createWin32SurfaceKHR(surfaceCreateInfo);
+ assert(surface);
+}
+
+Window::~Window()
+{
+ instance.destroySurfaceKHR(surface, nullptr);
+ DestroyWindow(window);
+ UnregisterClass("Window", moduleInstance);
+}
+
+vk::SurfaceKHR Window::getSurface()
+{
+ return surface;
+}
+
+void Window::show()
+{
+ ShowWindow(window, SW_SHOW);
+}
+
+#else
+# error Window class unimplemented for this platform
+#endif
diff --git a/tests/VulkanBenchmarks/Window.hpp b/tests/VulkanBenchmarks/Window.hpp
new file mode 100644
index 0000000..b4e8626
--- /dev/null
+++ b/tests/VulkanBenchmarks/Window.hpp
@@ -0,0 +1,61 @@
+// 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 BENCHMARKS_WINDOW_HPP_
+#define BENCHMARKS_WINDOW_HPP_
+
+#include "VulkanHeaders.hpp"
+
+#if defined(_WIN32)
+# define WIN32_LEAN_AND_MEAN
+# include <Windows.h>
+#endif
+
+#if USE_HEADLESS_SURFACE
+class Window
+{
+public:
+ Window(vk::Instance instance, vk::Extent2D windowSize);
+ ~Window();
+ vk::SurfaceKHR getSurface();
+ void show();
+
+private:
+ const vk::Instance instance;
+ vk::SurfaceKHR surface;
+};
+
+#elif defined(_WIN32)
+
+class Window
+{
+public:
+ Window(vk::Instance instance, vk::Extent2D windowSize);
+ ~Window();
+ vk::SurfaceKHR getSurface();
+ void show();
+
+private:
+ HWND window;
+ HINSTANCE moduleInstance;
+ WNDCLASSEX windowClass;
+ const vk::Instance instance;
+ vk::SurfaceKHR surface;
+};
+
+#else
+# error Window class unimplemented for this platform
+#endif
+
+#endif // BENCHMARKS_WINDOW_HPP_