blob: 1bbf369048cefe010f8029155dd01cf3a19edf5d [file] [log] [blame] [edit]
// 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"
#include "DrawTester.hpp"
#include "benchmark/benchmark.h"
#include <cassert>
#include <vector>
template<typename T>
static void RunBenchmark(benchmark::State &state, T &tester)
{
tester.initialize();
if(false) tester.show(); // Enable for visual verification.
// Warmup
tester.renderFrame();
for(auto _ : state)
{
tester.renderFrame();
}
}
static void TriangleSolidColor(benchmark::State &state, Multisample multisample)
{
DrawTester tester(multisample);
tester.onCreateVertexBuffers([](DrawTester &tester) {
struct Vertex
{
float position[3];
};
Vertex vertexBufferData[] = {
{ { 1.0f, 1.0f, 0.5f } },
{ { -1.0f, 1.0f, 0.5f } },
{ { 0.0f, -1.0f, 0.5f } }
};
std::vector<vk::VertexInputAttributeDescription> inputAttributes;
inputAttributes.push_back(vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position)));
tester.addVertexBuffer(vertexBufferData, sizeof(vertexBufferData), std::move(inputAttributes));
});
tester.onCreateVertexShader([](DrawTester &tester) {
const char *vertexShader = R"(#version 310 es
layout(location = 0) in vec3 inPos;
void main()
{
gl_Position = vec4(inPos.xyz, 1.0);
})";
return tester.createShaderModule(vertexShader, EShLanguage::EShLangVertex);
});
tester.onCreateFragmentShader([](DrawTester &tester) {
const char *fragmentShader = R"(#version 310 es
precision highp float;
layout(location = 0) out vec4 outColor;
void main()
{
outColor = vec4(1.0, 1.0, 1.0, 1.0);
})";
return tester.createShaderModule(fragmentShader, EShLanguage::EShLangFragment);
});
RunBenchmark(state, tester);
}
static void TriangleInterpolateColor(benchmark::State &state, Multisample multisample)
{
DrawTester tester(multisample);
tester.onCreateVertexBuffers([](DrawTester &tester) {
struct Vertex
{
float position[3];
float color[3];
};
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 } }
};
std::vector<vk::VertexInputAttributeDescription> inputAttributes;
inputAttributes.push_back(vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position)));
inputAttributes.push_back(vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, color)));
tester.addVertexBuffer(vertexBufferData, sizeof(vertexBufferData), std::move(inputAttributes));
});
tester.onCreateVertexShader([](DrawTester &tester) {
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;
void main()
{
outColor = inColor;
gl_Position = vec4(inPos.xyz, 1.0);
})";
return tester.createShaderModule(vertexShader, EShLanguage::EShLangVertex);
});
tester.onCreateFragmentShader([](DrawTester &tester) {
const char *fragmentShader = R"(#version 310 es
precision highp float;
layout(location = 0) in vec3 inColor;
layout(location = 0) out vec4 outColor;
void main()
{
outColor = vec4(inColor, 1.0);
})";
return tester.createShaderModule(fragmentShader, EShLanguage::EShLangFragment);
});
RunBenchmark(state, tester);
}
static void TriangleSampleTexture(benchmark::State &state, Multisample multisample)
{
DrawTester tester(multisample);
tester.onCreateVertexBuffers([](DrawTester &tester) {
struct Vertex
{
float position[3];
float texCoord[2];
};
Vertex vertexBufferData[] = {
{ { 1.0f, 1.0f, 0.5f }, { 1.0f, 0.0f } },
{ { -1.0f, 1.0f, 0.5f }, { 0.0f, 1.0f } },
{ { 0.0f, -1.0f, 0.5f }, { 0.0f, 0.0f } }
};
std::vector<vk::VertexInputAttributeDescription> inputAttributes;
inputAttributes.push_back(vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position)));
inputAttributes.push_back(vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, texCoord)));
tester.addVertexBuffer(vertexBufferData, sizeof(vertexBufferData), std::move(inputAttributes));
});
tester.onCreateVertexShader([](DrawTester &tester) {
const char *vertexShader = R"(#version 310 es
layout(location = 0) in vec3 inPos;
layout(location = 1) in vec2 inTexCoord;
layout(location = 0) out vec2 outTexCoord;
void main()
{
gl_Position = vec4(inPos.xyz, 1.0);
outTexCoord = inTexCoord;
})";
return tester.createShaderModule(vertexShader, EShLanguage::EShLangVertex);
});
tester.onCreateFragmentShader([](DrawTester &tester) {
const char *fragmentShader = R"(#version 310 es
precision highp float;
layout(location = 0) in vec2 inTexCoord;
layout(location = 0) out vec4 outColor;
layout(binding = 0) uniform sampler2D texSampler;
void main()
{
outColor = texture(texSampler, inTexCoord);
})";
return tester.createShaderModule(fragmentShader, EShLanguage::EShLangFragment);
});
tester.onCreateDescriptorSetLayouts([](DrawTester &tester) -> std::vector<vk::DescriptorSetLayoutBinding> {
vk::DescriptorSetLayoutBinding samplerLayoutBinding;
samplerLayoutBinding.binding = 1;
samplerLayoutBinding.descriptorCount = 1;
samplerLayoutBinding.descriptorType = vk::DescriptorType::eCombinedImageSampler;
samplerLayoutBinding.pImmutableSamplers = nullptr;
samplerLayoutBinding.stageFlags = vk::ShaderStageFlagBits::eFragment;
return { samplerLayoutBinding };
});
tester.onUpdateDescriptorSet([](DrawTester &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet) {
auto &device = tester.getDevice();
auto &physicalDevice = tester.getPhysicalDevice();
auto &queue = tester.getQueue();
auto &texture = tester.addImage(device, physicalDevice, 16, 16, vk::Format::eR8G8B8A8Unorm).obj;
// Fill texture with colorful checkerboard
std::array<uint32_t, 3> rgb = { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF };
int colorIndex = 0;
vk::DeviceSize bufferSize = 16 * 16 * 4;
Buffer buffer(device, bufferSize, vk::BufferUsageFlagBits::eTransferSrc);
uint32_t *data = static_cast<uint32_t *>(buffer.mapMemory());
for(int i = 0; i < 16; i++)
{
for(int j = 0; j < 16; j++)
{
if(((i ^ j) & 1) == 0)
{
data[i + 16 * j] = rgb[colorIndex++ % rgb.size()];
}
else
{
data[i + 16 * j] = 0;
}
}
}
buffer.unmapMemory();
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;
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;
auto sampler = tester.addSampler(samplerInfo);
vk::DescriptorImageInfo imageInfo;
imageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
imageInfo.imageView = texture.getImageView();
imageInfo.sampler = sampler.obj;
std::array<vk::WriteDescriptorSet, 1> descriptorWrites = {};
descriptorWrites[0].dstSet = descriptorSet;
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);
});
RunBenchmark(state, tester);
}
BENCHMARK_CAPTURE(TriangleSolidColor, TriangleSolidColor, Multisample::False)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
BENCHMARK_CAPTURE(TriangleInterpolateColor, TriangleInterpolateColor, Multisample::False)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
BENCHMARK_CAPTURE(TriangleSampleTexture, TriangleSampleTexture, Multisample::False)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
BENCHMARK_CAPTURE(TriangleSolidColor, TriangleSolidColor_Multisample, Multisample::True)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
BENCHMARK_CAPTURE(TriangleInterpolateColor, TriangleInterpolateColor_Multisample, Multisample::True)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
BENCHMARK_CAPTURE(TriangleSampleTexture, TriangleSampleTexture_Multisample, Multisample::True)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();