| // 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 "VulkanTester.hpp" | |
| #include "benchmark/benchmark.h" | |
| #include <cassert> | |
| class ClearImageBenchmark | |
| { | |
| public: | |
| void initialize(vk::Format clearFormat, vk::ImageAspectFlagBits clearAspect) | |
| { | |
| tester.initialize(); | |
| auto &device = tester.getDevice(); | |
| auto &physicalDevice = tester.getPhysicalDevice(); | |
| vk::ImageCreateInfo imageInfo; | |
| imageInfo.imageType = vk::ImageType::e2D; | |
| imageInfo.format = clearFormat; | |
| imageInfo.tiling = vk::ImageTiling::eOptimal; | |
| imageInfo.initialLayout = vk::ImageLayout::eUndefined; | |
| imageInfo.usage = vk::ImageUsageFlagBits::eTransferDst; | |
| imageInfo.samples = vk::SampleCountFlagBits::e4; | |
| imageInfo.extent = vk::Extent3D(1024, 1024, 1); | |
| imageInfo.mipLevels = 1; | |
| imageInfo.arrayLayers = 1; | |
| image = device.createImage(imageInfo); | |
| vk::MemoryRequirements memoryRequirements = device.getImageMemoryRequirements(image); | |
| vk::MemoryAllocateInfo allocateInfo; | |
| allocateInfo.allocationSize = memoryRequirements.size; | |
| allocateInfo.memoryTypeIndex = Util::getMemoryTypeIndex(physicalDevice, memoryRequirements.memoryTypeBits); | |
| memory = device.allocateMemory(allocateInfo); | |
| device.bindImageMemory(image, memory, 0); | |
| vk::CommandPoolCreateInfo commandPoolCreateInfo; | |
| commandPoolCreateInfo.queueFamilyIndex = tester.getQueueFamilyIndex(); | |
| commandPool = device.createCommandPool(commandPoolCreateInfo); | |
| vk::CommandBufferAllocateInfo commandBufferAllocateInfo; | |
| commandBufferAllocateInfo.commandPool = commandPool; | |
| commandBufferAllocateInfo.commandBufferCount = 1; | |
| commandBuffer = device.allocateCommandBuffers(commandBufferAllocateInfo)[0]; | |
| vk::CommandBufferBeginInfo commandBufferBeginInfo; | |
| commandBufferBeginInfo.flags = {}; | |
| commandBuffer.begin(commandBufferBeginInfo); | |
| vk::ImageMemoryBarrier imageMemoryBarrier; | |
| imageMemoryBarrier.image = image; | |
| imageMemoryBarrier.subresourceRange.aspectMask = clearAspect; | |
| imageMemoryBarrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; | |
| imageMemoryBarrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; | |
| imageMemoryBarrier.oldLayout = vk::ImageLayout::eUndefined; | |
| imageMemoryBarrier.newLayout = vk::ImageLayout::eGeneral; | |
| commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eTopOfPipe, | |
| vk::DependencyFlagBits::eDeviceGroup, {}, {}, imageMemoryBarrier); | |
| vk::ImageSubresourceRange range; | |
| range.aspectMask = clearAspect; | |
| range.baseMipLevel = 0; | |
| range.levelCount = 1; | |
| range.baseArrayLayer = 0; | |
| range.layerCount = 1; | |
| if(clearAspect == vk::ImageAspectFlagBits::eColor) | |
| { | |
| vk::ClearColorValue clearColorValue; | |
| clearColorValue.float32[0] = 0.0f; | |
| clearColorValue.float32[1] = 1.0f; | |
| clearColorValue.float32[2] = 0.0f; | |
| clearColorValue.float32[3] = 1.0f; | |
| commandBuffer.clearColorImage(image, vk::ImageLayout::eGeneral, &clearColorValue, 1, &range); | |
| } | |
| else if(clearAspect == vk::ImageAspectFlagBits::eDepth) | |
| { | |
| vk::ClearDepthStencilValue clearDepthStencilValue; | |
| clearDepthStencilValue.depth = 1.0f; | |
| clearDepthStencilValue.stencil = 0xFF; | |
| commandBuffer.clearDepthStencilImage(image, vk::ImageLayout::eGeneral, &clearDepthStencilValue, 1, &range); | |
| } | |
| else | |
| assert(false); | |
| commandBuffer.end(); | |
| } | |
| ~ClearImageBenchmark() | |
| { | |
| auto &device = tester.getDevice(); | |
| device.freeCommandBuffers(commandPool, 1, &commandBuffer); | |
| device.destroyCommandPool(commandPool, nullptr); | |
| device.freeMemory(memory, nullptr); | |
| device.destroyImage(image, nullptr); | |
| } | |
| void clear() | |
| { | |
| auto &queue = tester.getQueue(); | |
| vk::SubmitInfo submitInfo; | |
| submitInfo.commandBufferCount = 1; | |
| submitInfo.pCommandBuffers = &commandBuffer; | |
| queue.submit(1, &submitInfo, nullptr); | |
| queue.waitIdle(); | |
| } | |
| private: | |
| VulkanTester tester; | |
| vk::Image image; // Owning handle | |
| vk::DeviceMemory memory; // Owning handle | |
| vk::CommandPool commandPool; // Owning handle | |
| vk::CommandBuffer commandBuffer; // Owning handle | |
| }; | |
| static void ClearImage(benchmark::State &state, vk::Format clearFormat, vk::ImageAspectFlagBits clearAspect) | |
| { | |
| ClearImageBenchmark benchmark; | |
| benchmark.initialize(clearFormat, clearAspect); | |
| // Execute once to have the Reactor routine generated. | |
| benchmark.clear(); | |
| for(auto _ : state) | |
| { | |
| benchmark.clear(); | |
| } | |
| } | |
| BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_R8G8B8A8_UNORM, vk::Format::eR8G8B8A8Unorm, vk::ImageAspectFlagBits::eColor)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime(); | |
| BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_R32_SFLOAT, vk::Format::eR32Sfloat, vk::ImageAspectFlagBits::eColor)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime(); | |
| BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_D32_SFLOAT, vk::Format::eD32Sfloat, vk::ImageAspectFlagBits::eDepth)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime(); |