290 lines
9.5 KiB
C++
290 lines
9.5 KiB
C++
// 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();
|