VulkanBenchmarks: add texture sampling to Triangle benchmarks
This change was originally started by capn@, which added texture
sampling to the Triangle benchmarks. I finished up this change with the
following changes and fixes:
* Implement a correct fill texture to white using copyBufferToImage.
* Add Buffer class to wrap vk::Buffer and vk::DeviceMemory.
* Add support for using a VK_EXT_headless_surface Window, which is the
default on non-Windows platforms for now. On Windows, can be forced to
use this by defining USE_HEADLESS_SURFACE = 1.
* Fix out of bounds access because renderPassBeginInfo.clearValueCount
was set to 2 instead of 1.
* Fix illegal access to destructed ArrayRef in call to
commandBuffers[i].bindVertexBuffers.
* Make it build and run on Linux (fix compilation errors and use
aforementioned headless surface mode)
Bug: b/176981107
Change-Id: If82496315e77a062c024766863a1ca01e6b424f9
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/51668
Kokoro-Result: Antonio Maiorano <amaiorano@google.com>
Tested-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/tests/VulkanBenchmarks/CMakeLists.txt b/tests/VulkanBenchmarks/CMakeLists.txt
index 851ac91..3585067 100644
--- a/tests/VulkanBenchmarks/CMakeLists.txt
+++ b/tests/VulkanBenchmarks/CMakeLists.txt
@@ -13,7 +13,6 @@
# limitations under the License.
set(ROOT_PROJECT_COMPILE_OPTIONS
- ${SWIFTSHADER_COMPILE_OPTIONS}
${WARNINGS_AS_ERRORS}
)
diff --git a/tests/VulkanBenchmarks/VulkanBenchmarks.cpp b/tests/VulkanBenchmarks/VulkanBenchmarks.cpp
index 6b47b77..eb68aab 100644
--- a/tests/VulkanBenchmarks/VulkanBenchmarks.cpp
+++ b/tests/VulkanBenchmarks/VulkanBenchmarks.cpp
@@ -14,7 +14,19 @@
#include "benchmark/benchmark.h"
-#define VK_USE_PLATFORM_WIN32_KHR
+#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
#include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
@@ -23,19 +35,148 @@
#include "StandAlone/ResourceLimits.h"
#include "glslang/Public/ShaderLang.h"
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
+#if defined(_WIN32)
+# define WIN32_LEAN_AND_MEAN
+# include <Windows.h>
+#endif
#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:
VulkanBenchmark()
{
// TODO(b/158231104): Other platforms
+#if defined(_WIN32)
dl = std::make_unique<vk::DynamicLoader>("./vk_swiftshader.dll");
+#elif defined(__linux__)
+ dl = std::make_unique<vk::DynamicLoader>("./libvk_swiftshader.so");
+#else
+# error Unimplemented platform
+#endif
assert(dl->success());
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl->getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
@@ -71,25 +212,6 @@
}
protected:
- uint32_t getMemoryTypeIndex(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;
- }
-
const uint32_t queueFamilyIndex = 0;
vk::Instance instance;
@@ -178,7 +300,7 @@
~ClearImageBenchmark()
{
- device.freeCommandBuffers(commandPool, { commandBuffer });
+ device.freeCommandBuffers(commandPool, 1, &commandBuffer);
device.destroyCommandPool(commandPool, nullptr);
device.freeMemory(memory, nullptr);
device.destroyImage(image, nullptr);
@@ -214,17 +336,42 @@
benchmark.clear();
}
}
-BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_R8G8B8A8_UNORM, vk::Format::eR8G8B8A8Unorm, vk::ImageAspectFlagBits::eColor)->Unit(benchmark::kMillisecond);
-BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_R32_SFLOAT, vk::Format::eR32Sfloat, vk::ImageAspectFlagBits::eColor)->Unit(benchmark::kMillisecond);
-BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_D32_SFLOAT, vk::Format::eD32Sfloat, vk::ImageAspectFlagBits::eDepth)->Unit(benchmark::kMillisecond);
+#if USE_HEADLESS_SURFACE
class Window
{
public:
Window(vk::Instance instance, vk::Extent2D windowSize)
{
- moduleInstance = GetModuleHandle(NULL);
+ 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;
@@ -274,7 +421,6 @@
~Window()
{
instance.destroySurfaceKHR(surface, nullptr);
-
DestroyWindow(window);
UnregisterClass("Window", moduleInstance);
}
@@ -293,10 +439,12 @@
HWND window;
HINSTANCE moduleInstance;
WNDCLASSEX windowClass;
-
const vk::Instance instance;
vk::SurfaceKHR surface;
};
+#else
+# error Window class unimplemented for this platform
+#endif
class Swapchain
{
@@ -308,13 +456,14 @@
// 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 = surfaceCapabilities.currentExtent;
+ swapchainCreateInfo.imageExtent = extent;
swapchainCreateInfo.imageUsage = vk::ImageUsageFlagBits::eColorAttachment;
swapchainCreateInfo.preTransform = vk::SurfaceTransformFlagBitsKHR::eIdentity;
swapchainCreateInfo.imageArrayLayers = 1;
@@ -383,17 +532,75 @@
return imageViews[i];
}
+ vk::Extent2D getExtent() const
+ {
+ return extent;
+ }
+
const vk::Format colorFormat = vk::Format::eB8G8R8A8Unorm;
private:
const vk::Device device;
vk::SwapchainKHR swapchain;
+ vk::Extent2D extent;
std::vector<vk::Image> images; // Weak pointers. Presentable images owned by swapchain object.
std::vector<vk::ImageView> imageViews;
};
+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;
+ vk::DeviceMemory bufferMemory;
+};
+
class Image
{
public:
@@ -443,6 +650,11 @@
device.freeMemory(imageMemory);
}
+ vk::Image getImage()
+ {
+ return image;
+ }
+
vk::ImageView getImageView()
{
return imageView;
@@ -459,14 +671,14 @@
class Framebuffer
{
public:
- Framebuffer(vk::Device device, vk::ImageView attachment, vk::Format colorFormat, vk::RenderPass renderPass, uint32_t width, uint32_t height, bool multisample)
+ 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 = new Image(device, width, height, colorFormat, vk::SampleCountFlagBits::e4);
+ multisampleImage = new Image(device, extent.width, extent.height, colorFormat, vk::SampleCountFlagBits::e4);
// We'll be rendering to attachment location 0
attachments[0] = multisampleImage->getImageView();
@@ -482,8 +694,8 @@
framebufferCreateInfo.renderPass = renderPass;
framebufferCreateInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
framebufferCreateInfo.pAttachments = attachments.data();
- framebufferCreateInfo.width = width;
- framebufferCreateInfo.height = height;
+ framebufferCreateInfo.width = extent.width;
+ framebufferCreateInfo.height = extent.height;
framebufferCreateInfo.layers = 1;
framebuffer = device.createFramebuffer(framebufferCreateInfo);
@@ -569,6 +781,12 @@
~TriangleBenchmark()
{
+ delete texture;
+
+ device.destroyDescriptorPool(descriptorPool);
+
+ device.destroySampler(sampler, nullptr);
+
device.destroyPipelineLayout(pipelineLayout, nullptr);
device.destroyPipelineCache(pipelineCache, nullptr);
@@ -648,9 +866,72 @@
commandPoolCreateInfo.flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer;
commandPool = device.createCommandPool(commandPoolCreateInfo);
+ texture = new Image(device, 16, 16, vk::Format::eR8G8B8A8Unorm);
+
+ // Fill texture with white
+ vk::DeviceSize bufferSize = 16 * 16 * 4;
+ Buffer buffer(device, bufferSize, vk::BufferUsageFlagBits::eTransferSrc);
+ void *data = buffer.mapMemory();
+ 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);
+
+ vk::SamplerCreateInfo samplerInfo;
+ samplerInfo.magFilter = vk::Filter::eLinear;
+ samplerInfo.minFilter = vk::Filter::eLinear;
+ samplerInfo.addressModeU = vk::SamplerAddressMode::eRepeat;
+ samplerInfo.addressModeV = vk::SamplerAddressMode::eRepeat;
+ samplerInfo.addressModeW = vk::SamplerAddressMode::eRepeat;
+ samplerInfo.anisotropyEnable = VK_FALSE;
+ samplerInfo.unnormalizedCoordinates = VK_FALSE;
+ samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear;
+ samplerInfo.mipLodBias = 0.0f;
+ samplerInfo.minLod = 0.0f;
+ samplerInfo.maxLod = 0.0f;
+
+ sampler = device.createSampler(samplerInfo);
+
+ std::array<vk::DescriptorPoolSize, 1> poolSizes = {};
+ poolSizes[0].type = vk::DescriptorType::eCombinedImageSampler;
+ poolSizes[0].descriptorCount = 1;
+
+ vk::DescriptorPoolCreateInfo poolInfo;
+ poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
+ poolInfo.pPoolSizes = poolSizes.data();
+ poolInfo.maxSets = 1;
+
+ descriptorPool = device.createDescriptorPool(poolInfo);
+
+ std::vector<vk::DescriptorSetLayout> layouts(1, descriptorSetLayout);
+ vk::DescriptorSetAllocateInfo allocInfo;
+ allocInfo.descriptorPool = descriptorPool;
+ allocInfo.descriptorSetCount = 1;
+ allocInfo.pSetLayouts = layouts.data();
+
+ std::vector<vk::DescriptorSet> descriptorSets = device.allocateDescriptorSets(allocInfo);
+
+ vk::DescriptorImageInfo imageInfo;
+ imageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
+ imageInfo.imageView = texture->getImageView();
+ imageInfo.sampler = sampler;
+
+ std::array<vk::WriteDescriptorSet, 1> descriptorWrites = {};
+
+ descriptorWrites[0].dstSet = descriptorSets[0];
+ descriptorWrites[0].dstBinding = 1;
+ descriptorWrites[0].dstArrayElement = 0;
+ descriptorWrites[0].descriptorType = vk::DescriptorType::eCombinedImageSampler;
+ descriptorWrites[0].descriptorCount = 1;
+ descriptorWrites[0].pImageInfo = &imageInfo;
+
+ device.updateDescriptorSets(static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
+
vk::CommandBufferAllocateInfo commandBufferAllocateInfo;
commandBufferAllocateInfo.commandPool = commandPool;
- commandBufferAllocateInfo.commandBufferCount = swapchain->imageCount();
+ commandBufferAllocateInfo.commandBufferCount = static_cast<uint32_t>(swapchain->imageCount());
commandBufferAllocateInfo.level = vk::CommandBufferLevel::ePrimary;
commandBuffers = device.allocateCommandBuffers(commandBufferAllocateInfo);
@@ -669,20 +950,23 @@
renderPassBeginInfo.renderArea.offset.x = 0;
renderPassBeginInfo.renderArea.offset.y = 0;
renderPassBeginInfo.renderArea.extent = windowSize;
- renderPassBeginInfo.clearValueCount = 2;
+ renderPassBeginInfo.clearValueCount = ARRAY_SIZE(clearValues);
renderPassBeginInfo.pClearValues = clearValues;
commandBuffers[i].beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline);
// Set dynamic state
- vk::Viewport viewport(0.0f, 0.0f, windowSize.width, windowSize.height, 0.0f, 1.0f);
+ vk::Viewport viewport(0.0f, 0.0f, static_cast<float>(windowSize.width), static_cast<float>(windowSize.height), 0.0f, 1.0f);
commandBuffers[i].setViewport(0, 1, &viewport);
vk::Rect2D scissor(vk::Offset2D(0, 0), windowSize);
commandBuffers[i].setScissor(0, 1, &scissor);
+ commandBuffers[i].bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, 1, &descriptorSets[0], 0, nullptr);
+
// Draw a triangle
commandBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.get());
- commandBuffers[i].bindVertexBuffers(0, { vertices.buffer }, { 0 });
+ VULKAN_HPP_NAMESPACE::DeviceSize offset = 0;
+ commandBuffers[i].bindVertexBuffers(0, 1, &vertices.buffer, &offset);
commandBuffers[i].draw(3, 1, 0, 0);
commandBuffers[i].endRenderPass();
@@ -696,12 +980,13 @@
{
float position[3];
float color[3];
+ float texCoord[2];
};
Vertex vertexBufferData[] = {
- { { 1.0f, 1.0f, 0.05f }, { 1.0f, 0.0f, 0.0f } },
- { { -1.0f, 1.0f, 0.5f }, { 0.0f, 1.0f, 0.0f } },
- { { 0.0f, -1.0f, 0.5f }, { 0.0f, 0.0f, 1.0f } }
+ { { 1.0f, 1.0f, 0.05f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f } },
+ { { -1.0f, 1.0f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f } },
+ { { 0.0f, -1.0f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f } }
};
vk::BufferCreateInfo vertexBufferInfo;
@@ -712,7 +997,7 @@
vk::MemoryAllocateInfo memoryAllocateInfo;
vk::MemoryRequirements memoryRequirements = device.getBufferMemoryRequirements(vertices.buffer);
memoryAllocateInfo.allocationSize = memoryRequirements.size;
- memoryAllocateInfo.memoryTypeIndex = getMemoryTypeIndex(memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
+ memoryAllocateInfo.memoryTypeIndex = getMemoryTypeIndex(physicalDevice, memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
vk::DeviceMemory vertexBufferMemory = device.allocateMemory(memoryAllocateInfo);
void *data = device.mapMemory(vertexBufferMemory, 0, VK_WHOLE_SIZE);
@@ -726,6 +1011,7 @@
vertices.inputAttributes.push_back(vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position)));
vertices.inputAttributes.push_back(vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, color)));
+ vertices.inputAttributes.push_back(vk::VertexInputAttributeDescription(2, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, texCoord)));
vertices.inputState.vertexBindingDescriptionCount = 1;
vertices.inputState.pVertexBindingDescriptions = &vertices.inputBinding;
@@ -739,7 +1025,7 @@
for(size_t i = 0; i < framebuffers.size(); i++)
{
- framebuffers[i] = new Framebuffer(device, swapchain->getImageView(i), swapchain->colorFormat, renderPass, windowSize.width, windowSize.height, multisample);
+ framebuffers[i] = new Framebuffer(device, swapchain->getImageView(i), swapchain->colorFormat, renderPass, swapchain->getExtent(), multisample);
}
}
@@ -837,9 +1123,26 @@
vk::UniquePipeline createGraphicsPipeline(vk::RenderPass renderPass)
{
- vk::PipelineLayoutCreateInfo pPipelineLayoutCreateInfo;
- pPipelineLayoutCreateInfo.setLayoutCount = 0;
- pipelineLayout = device.createPipelineLayout(pPipelineLayoutCreateInfo);
+ vk::DescriptorSetLayoutBinding samplerLayoutBinding;
+ samplerLayoutBinding.binding = 1;
+ samplerLayoutBinding.descriptorCount = 1;
+ samplerLayoutBinding.descriptorType = vk::DescriptorType::eCombinedImageSampler;
+ samplerLayoutBinding.pImmutableSamplers = nullptr;
+ samplerLayoutBinding.stageFlags = vk::ShaderStageFlagBits::eFragment;
+
+ std::array<vk::DescriptorSetLayoutBinding, 1> bindings = { samplerLayoutBinding };
+ vk::DescriptorSetLayoutCreateInfo layoutInfo;
+ layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
+ layoutInfo.pBindings = bindings.data();
+
+ descriptorSetLayout = device.createDescriptorSetLayout(layoutInfo);
+
+ std::vector<vk::DescriptorSetLayout> setLayouts(1, descriptorSetLayout);
+
+ vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
+ pipelineLayoutCreateInfo.setLayoutCount = static_cast<uint32_t>(setLayouts.size());
+ pipelineLayoutCreateInfo.pSetLayouts = setLayouts.data();
+ pipelineLayout = device.createPipelineLayout(pipelineLayoutCreateInfo);
vk::GraphicsPipelineCreateInfo pipelineCreateInfo;
pipelineCreateInfo.layout = pipelineLayout;
@@ -893,12 +1196,15 @@
const char *vertexShader = R"(#version 310 es
layout(location = 0) in vec3 inPos;
layout(location = 1) in vec3 inColor;
+
layout(location = 0) out vec3 outColor;
+ layout(location = 1) out vec2 fragTexCoord;
void main()
{
outColor = inColor;
gl_Position = vec4(inPos.xyz, 1.0);
+ fragTexCoord = inPos.xy;
}
)";
@@ -906,11 +1212,15 @@
precision highp float;
layout(location = 0) in vec3 inColor;
+ layout(location = 1) in vec2 fragTexCoord;
+
layout(location = 0) out vec4 outColor;
+ layout(binding = 0) uniform sampler2D texSampler;
+
void main()
{
- outColor = vec4(inColor, 1.0);
+ outColor = texture(texSampler, fragTexCoord) * vec4(inColor, 1.0);
}
)";
@@ -962,10 +1272,14 @@
std::vector<vk::VertexInputAttributeDescription> inputAttributes;
} vertices;
+ vk::DescriptorPool descriptorPool;
+ vk::DescriptorSetLayout descriptorSetLayout;
vk::PipelineLayout pipelineLayout;
vk::PipelineCache pipelineCache;
vk::UniquePipeline pipeline;
+ vk::Sampler sampler;
+
vk::CommandPool commandPool;
std::vector<vk::CommandBuffer> commandBuffers;
@@ -973,6 +1287,8 @@
vk::Semaphore renderCompleteSemaphore;
std::vector<vk::Fence> waitFences;
+
+ Image *texture = nullptr;
};
static void Triangle(benchmark::State &state, bool multisample)
@@ -989,5 +1305,9 @@
benchmark.renderFrame();
}
}
+
+BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_R8G8B8A8_UNORM, vk::Format::eR8G8B8A8Unorm, vk::ImageAspectFlagBits::eColor)->Unit(benchmark::kMillisecond);
+BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_R32_SFLOAT, vk::Format::eR32Sfloat, vk::ImageAspectFlagBits::eColor)->Unit(benchmark::kMillisecond);
+BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_D32_SFLOAT, vk::Format::eD32Sfloat, vk::ImageAspectFlagBits::eDepth)->Unit(benchmark::kMillisecond);
BENCHMARK_CAPTURE(Triangle, Hello, false)->Unit(benchmark::kMillisecond);
BENCHMARK_CAPTURE(Triangle, Multisample, true)->Unit(benchmark::kMillisecond);