1 // Copyright 2021 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "Util.hpp"
16 #include "VulkanTester.hpp"
17
18 #include "benchmark/benchmark.h"
19
20 #include <cassert>
21
22 class ClearImageBenchmark
23 {
24 public:
initialize(vk::Format clearFormat,vk::ImageAspectFlagBits clearAspect)25 void initialize(vk::Format clearFormat, vk::ImageAspectFlagBits clearAspect)
26 {
27 tester.initialize();
28 auto &device = tester.getDevice();
29 auto &physicalDevice = tester.getPhysicalDevice();
30
31 vk::ImageCreateInfo imageInfo;
32 imageInfo.imageType = vk::ImageType::e2D;
33 imageInfo.format = clearFormat;
34 imageInfo.tiling = vk::ImageTiling::eOptimal;
35 imageInfo.initialLayout = vk::ImageLayout::eUndefined;
36 imageInfo.usage = vk::ImageUsageFlagBits::eTransferDst;
37 imageInfo.samples = vk::SampleCountFlagBits::e4;
38 imageInfo.extent = vk::Extent3D(1024, 1024, 1);
39 imageInfo.mipLevels = 1;
40 imageInfo.arrayLayers = 1;
41
42 image = device.createImage(imageInfo);
43
44 vk::MemoryRequirements memoryRequirements = device.getImageMemoryRequirements(image);
45
46 vk::MemoryAllocateInfo allocateInfo;
47 allocateInfo.allocationSize = memoryRequirements.size;
48 allocateInfo.memoryTypeIndex = Util::getMemoryTypeIndex(physicalDevice, memoryRequirements.memoryTypeBits);
49
50 memory = device.allocateMemory(allocateInfo);
51
52 device.bindImageMemory(image, memory, 0);
53
54 vk::CommandPoolCreateInfo commandPoolCreateInfo;
55 commandPoolCreateInfo.queueFamilyIndex = tester.getQueueFamilyIndex();
56
57 commandPool = device.createCommandPool(commandPoolCreateInfo);
58
59 vk::CommandBufferAllocateInfo commandBufferAllocateInfo;
60 commandBufferAllocateInfo.commandPool = commandPool;
61 commandBufferAllocateInfo.commandBufferCount = 1;
62
63 commandBuffer = device.allocateCommandBuffers(commandBufferAllocateInfo)[0];
64
65 vk::CommandBufferBeginInfo commandBufferBeginInfo;
66 commandBufferBeginInfo.flags = {};
67
68 commandBuffer.begin(commandBufferBeginInfo);
69
70 vk::ImageMemoryBarrier imageMemoryBarrier;
71 imageMemoryBarrier.image = image;
72 imageMemoryBarrier.subresourceRange.aspectMask = clearAspect;
73 imageMemoryBarrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
74 imageMemoryBarrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
75 imageMemoryBarrier.oldLayout = vk::ImageLayout::eUndefined;
76 imageMemoryBarrier.newLayout = vk::ImageLayout::eGeneral;
77 commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eTopOfPipe,
78 vk::DependencyFlagBits::eDeviceGroup, {}, {}, imageMemoryBarrier);
79
80 vk::ImageSubresourceRange range;
81 range.aspectMask = clearAspect;
82 range.baseMipLevel = 0;
83 range.levelCount = 1;
84 range.baseArrayLayer = 0;
85 range.layerCount = 1;
86
87 if(clearAspect == vk::ImageAspectFlagBits::eColor)
88 {
89 vk::ClearColorValue clearColorValue;
90 clearColorValue.float32[0] = 0.0f;
91 clearColorValue.float32[1] = 1.0f;
92 clearColorValue.float32[2] = 0.0f;
93 clearColorValue.float32[3] = 1.0f;
94
95 commandBuffer.clearColorImage(image, vk::ImageLayout::eGeneral, &clearColorValue, 1, &range);
96 }
97 else if(clearAspect == vk::ImageAspectFlagBits::eDepth)
98 {
99 vk::ClearDepthStencilValue clearDepthStencilValue;
100 clearDepthStencilValue.depth = 1.0f;
101 clearDepthStencilValue.stencil = 0xFF;
102
103 commandBuffer.clearDepthStencilImage(image, vk::ImageLayout::eGeneral, &clearDepthStencilValue, 1, &range);
104 }
105 else
106 assert(false);
107
108 commandBuffer.end();
109 }
110
~ClearImageBenchmark()111 ~ClearImageBenchmark()
112 {
113 auto &device = tester.getDevice();
114 device.freeCommandBuffers(commandPool, 1, &commandBuffer);
115 device.destroyCommandPool(commandPool, nullptr);
116 device.freeMemory(memory, nullptr);
117 device.destroyImage(image, nullptr);
118 }
119
clear()120 void clear()
121 {
122 auto &queue = tester.getQueue();
123
124 vk::SubmitInfo submitInfo;
125 submitInfo.commandBufferCount = 1;
126 submitInfo.pCommandBuffers = &commandBuffer;
127
128 queue.submit(1, &submitInfo, nullptr);
129 queue.waitIdle();
130 }
131
132 private:
133 VulkanTester tester;
134 vk::Image image; // Owning handle
135 vk::DeviceMemory memory; // Owning handle
136 vk::CommandPool commandPool; // Owning handle
137 vk::CommandBuffer commandBuffer; // Owning handle
138 };
139
ClearImage(benchmark::State & state,vk::Format clearFormat,vk::ImageAspectFlagBits clearAspect)140 static void ClearImage(benchmark::State &state, vk::Format clearFormat, vk::ImageAspectFlagBits clearAspect)
141 {
142 ClearImageBenchmark benchmark;
143 benchmark.initialize(clearFormat, clearAspect);
144
145 // Execute once to have the Reactor routine generated.
146 benchmark.clear();
147
148 for(auto _ : state)
149 {
150 benchmark.clear();
151 }
152 }
153
154 BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_R8G8B8A8_UNORM, vk::Format::eR8G8B8A8Unorm, vk::ImageAspectFlagBits::eColor)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
155 BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_R32_SFLOAT, vk::Format::eR32Sfloat, vk::ImageAspectFlagBits::eColor)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
156 BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_D32_SFLOAT, vk::Format::eD32Sfloat, vk::ImageAspectFlagBits::eDepth)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
157