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: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarAntonio Maiorano <amaiorano@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com>
parent 22be66d4
// 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);
}
// 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_
...@@ -22,8 +22,22 @@ set(ROOT_PROJECT_LINK_LIBRARIES ...@@ -22,8 +22,22 @@ set(ROOT_PROJECT_LINK_LIBRARIES
) )
set(VULKAN_BENCHMARKS_SRC_FILES set(VULKAN_BENCHMARKS_SRC_FILES
VulkanBenchmarks.cpp Buffer.cpp
Buffer.hpp
Framebuffer.cpp
Framebuffer.hpp
Image.cpp
Image.hpp
main.cpp main.cpp
Swapchain.cpp
Swapchain.hpp
Util.cpp
Util.hpp
VulkanBenchmarks.cpp
VulkanHeaders.cpp
VulkanHeaders.hpp
Window.cpp
Window.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 "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);
}
// 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_
// 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);
}
// 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_
// 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);
}
// 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_
// 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, &region);
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
// 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_
...@@ -14,157 +14,19 @@ ...@@ -14,157 +14,19 @@
#include "benchmark/benchmark.h" #include "benchmark/benchmark.h"
#if !defined(USE_HEADLESS_SURFACE) #include "Buffer.hpp"
# define USE_HEADLESS_SURFACE 0 #include "Framebuffer.hpp"
#endif #include "Image.hpp"
#include "Swapchain.hpp"
#if !defined(_WIN32) #include "Util.hpp"
// @TODO: implement native Window support for current platform. For now, always use HeadlessSurface. #include "VulkanHeaders.hpp"
# undef USE_HEADLESS_SURFACE #include "Window.hpp"
# 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 <cassert> #include <cassert>
#include <vector> #include <vector>
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) #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, &region);
endSingleTimeCommands(device, commandPool, queue, commandBuffer);
}
} // namespace
class VulkanBenchmark class VulkanBenchmark
{ {
public: public:
...@@ -337,424 +199,6 @@ static void ClearImage(benchmark::State &state, vk::Format clearFormat, vk::Imag ...@@ -337,424 +199,6 @@ static void ClearImage(benchmark::State &state, vk::Format clearFormat, vk::Imag
} }
} }
#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 class TriangleBenchmark : public VulkanBenchmark
{ {
public: public:
...@@ -871,9 +315,9 @@ protected: ...@@ -871,9 +315,9 @@ protected:
memset(data, 255, bufferSize); memset(data, 255, bufferSize);
buffer.unmapMemory(); buffer.unmapMemory();
transitionImageLayout(device, commandPool, queue, texture->getImage(), vk::Format::eR8G8B8A8Unorm, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal); Util::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); Util::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::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal);
vk::SamplerCreateInfo samplerInfo; vk::SamplerCreateInfo samplerInfo;
samplerInfo.magFilter = vk::Filter::eLinear; samplerInfo.magFilter = vk::Filter::eLinear;
...@@ -993,7 +437,7 @@ protected: ...@@ -993,7 +437,7 @@ protected:
vk::MemoryAllocateInfo memoryAllocateInfo; vk::MemoryAllocateInfo memoryAllocateInfo;
vk::MemoryRequirements memoryRequirements = device.getBufferMemoryRequirements(vertices.buffer); vk::MemoryRequirements memoryRequirements = device.getBufferMemoryRequirements(vertices.buffer);
memoryAllocateInfo.allocationSize = memoryRequirements.size; 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); vertices.memory = device.allocateMemory(memoryAllocateInfo);
void *data = device.mapMemory(vertices.memory, 0, VK_WHOLE_SIZE); void *data = device.mapMemory(vertices.memory, 0, VK_WHOLE_SIZE);
...@@ -1108,7 +552,7 @@ protected: ...@@ -1108,7 +552,7 @@ protected:
vk::ShaderModule createShaderModule(const char *glslSource, EShLanguage glslLanguage) vk::ShaderModule createShaderModule(const char *glslSource, EShLanguage glslLanguage)
{ {
auto spirv = compileGLSLtoSPIRV(glslSource, glslLanguage); auto spirv = Util::compileGLSLtoSPIRV(glslSource, glslLanguage);
vk::ShaderModuleCreateInfo moduleCreateInfo; vk::ShaderModuleCreateInfo moduleCreateInfo;
moduleCreateInfo.codeSize = spirv.size() * sizeof(uint32_t); moduleCreateInfo.codeSize = spirv.size() * sizeof(uint32_t);
......
#include "VulkanHeaders.hpp"
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
// 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_
// 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
// 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_
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