VulkanBenchmarks: add solid and interpolated triangles tests
Generalized TriangleBenchmark to support rendering a triangle of a solid
color (hard-coded in shader), interpolated input colors, and
interpolated colors with texture sampling. Added benchmark captures for
each type, along with multi-sampled versions of each.
Bug: b/176981107
Change-Id: Iadef1f0f9a339038198f8ef0e492c4c2909a96b2
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/51889
Tested-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
diff --git a/tests/VulkanBenchmarks/VulkanBenchmarks.cpp b/tests/VulkanBenchmarks/VulkanBenchmarks.cpp
index 9196dd9..91e747e 100644
--- a/tests/VulkanBenchmarks/VulkanBenchmarks.cpp
+++ b/tests/VulkanBenchmarks/VulkanBenchmarks.cpp
@@ -199,11 +199,25 @@
}
}
+enum class FragShadeType
+{
+ Solid,
+ Interpolate,
+ Sample,
+};
+
+enum class Multisample
+{
+ False,
+ True
+};
+
class TriangleBenchmark : public VulkanBenchmark
{
public:
- TriangleBenchmark(bool multisample)
- : multisample(multisample)
+ TriangleBenchmark(FragShadeType fragShadeType, Multisample multisample)
+ : fragShadeType(fragShadeType)
+ , multisample(multisample == Multisample::True)
{
window.reset(new Window(instance, windowSize));
swapchain.reset(new Swapchain(physicalDevice, device, *window));
@@ -306,68 +320,72 @@
commandPoolCreateInfo.flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer;
commandPool = device.createCommandPool(commandPoolCreateInfo);
- texture.reset(new Image(device, 16, 16, vk::Format::eR8G8B8A8Unorm));
+ std::vector<vk::DescriptorSet> descriptorSets;
+ if(fragShadeType == FragShadeType::Sample)
+ {
+ texture.reset(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();
+ // 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();
- 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);
+ 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;
+ 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);
+ sampler = device.createSampler(samplerInfo);
- std::array<vk::DescriptorPoolSize, 1> poolSizes = {};
- poolSizes[0].type = vk::DescriptorType::eCombinedImageSampler;
- poolSizes[0].descriptorCount = 1;
+ 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;
+ vk::DescriptorPoolCreateInfo poolInfo;
+ poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
+ poolInfo.pPoolSizes = poolSizes.data();
+ poolInfo.maxSets = 1;
- descriptorPool = device.createDescriptorPool(poolInfo);
+ 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::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);
+ descriptorSets = device.allocateDescriptorSets(allocInfo);
- vk::DescriptorImageInfo imageInfo;
- imageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
- imageInfo.imageView = texture->getImageView();
- imageInfo.sampler = sampler;
+ vk::DescriptorImageInfo imageInfo;
+ imageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
+ imageInfo.imageView = texture->getImageView();
+ imageInfo.sampler = sampler;
- std::array<vk::WriteDescriptorSet, 1> descriptorWrites = {};
+ 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;
+ 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);
+ device.updateDescriptorSets(static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
+ }
vk::CommandBufferAllocateInfo commandBufferAllocateInfo;
commandBufferAllocateInfo.commandPool = commandPool;
@@ -401,7 +419,10 @@
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);
+ if(!descriptorSets.empty())
+ {
+ commandBuffers[i].bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, 1, &descriptorSets[0], 0, nullptr);
+ }
// Draw a triangle
commandBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
@@ -449,9 +470,26 @@
vertices.inputBinding.stride = sizeof(Vertex);
vertices.inputBinding.inputRate = vk::VertexInputRate::eVertex;
- 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)));
+ switch(fragShadeType)
+ {
+ case FragShadeType::Solid:
+ vertices.inputAttributes.push_back(vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position)));
+ break;
+
+ case FragShadeType::Interpolate:
+ 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)));
+ break;
+
+ case FragShadeType::Sample:
+ 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)));
+ break;
+
+ default:
+ assert(false && "Unhandled fragShadeType");
+ }
vertices.inputState.vertexBindingDescriptionCount = 1;
vertices.inputState.pVertexBindingDescriptions = &vertices.inputBinding;
@@ -563,21 +601,25 @@
vk::Pipeline createGraphicsPipeline(vk::RenderPass renderPass)
{
- vk::DescriptorSetLayoutBinding samplerLayoutBinding;
- samplerLayoutBinding.binding = 1;
- samplerLayoutBinding.descriptorCount = 1;
- samplerLayoutBinding.descriptorType = vk::DescriptorType::eCombinedImageSampler;
- samplerLayoutBinding.pImmutableSamplers = nullptr;
- samplerLayoutBinding.stageFlags = vk::ShaderStageFlagBits::eFragment;
+ std::vector<vk::DescriptorSetLayout> setLayouts;
+ if(fragShadeType == FragShadeType::Sample)
+ {
+ 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();
+ 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);
+ descriptorSetLayout = device.createDescriptorSetLayout(layoutInfo);
- std::vector<vk::DescriptorSetLayout> setLayouts(1, descriptorSetLayout);
+ setLayouts.push_back(descriptorSetLayout);
+ }
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
pipelineLayoutCreateInfo.setLayoutCount = static_cast<uint32_t>(setLayouts.size());
@@ -633,36 +675,98 @@
multisampleState.rasterizationSamples = multisample ? vk::SampleCountFlagBits::e4 : vk::SampleCountFlagBits::e1;
multisampleState.pSampleMask = nullptr;
- const char *vertexShader = R"(#version 310 es
- layout(location = 0) in vec3 inPos;
- layout(location = 1) in vec3 inColor;
+ const char *vertexShader = nullptr;
+ const char *fragmentShader = nullptr;
- layout(location = 0) out vec3 outColor;
- layout(location = 1) out vec2 fragTexCoord;
-
- void main()
+ switch(fragShadeType)
+ {
+ case FragShadeType::Solid:
{
- outColor = inColor;
- gl_Position = vec4(inPos.xyz, 1.0);
- fragTexCoord = inPos.xy;
+ vertexShader = R"(#version 310 es
+ layout(location = 0) in vec3 inPos;
+
+ void main()
+ {
+ gl_Position = vec4(inPos.xyz, 1.0);
+ })";
+
+ 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);
+ })";
}
- )";
+ break;
- const char *fragmentShader = R"(#version 310 es
- 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()
+ case FragShadeType::Interpolate:
{
- outColor = texture(texSampler, fragTexCoord) * vec4(inColor, 1.0);
+ 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);
+ })";
+
+ 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);
+ })";
}
- )";
+ break;
+
+ case FragShadeType::Sample:
+ {
+ 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;
+ })";
+
+ fragmentShader = R"(#version 310 es
+ 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 = texture(texSampler, fragTexCoord) * vec4(inColor, 1.0);
+ })";
+ }
+ break;
+
+ default:
+ assert(false && "Unhandled fragShadeType");
+ break;
+ }
vk::ShaderModule vertexModule = createShaderModule(vertexShader, EShLanguage::EShLangVertex);
vk::ShaderModule fragmentModule = createShaderModule(fragmentShader, EShLanguage::EShLangFragment);
@@ -698,6 +802,7 @@
}
const vk::Extent2D windowSize = { 1280, 720 };
+ const FragShadeType fragShadeType;
const bool multisample;
std::unique_ptr<Window> window;
@@ -732,9 +837,9 @@
std::vector<vk::CommandBuffer> commandBuffers; // Owning handles
};
-static void Triangle(benchmark::State &state, bool multisample)
+static void Triangle(benchmark::State &state, FragShadeType fragShadeType, Multisample multisample)
{
- TriangleBenchmark benchmark(multisample);
+ TriangleBenchmark benchmark(fragShadeType, multisample);
if(false) benchmark.show(); // Enable for visual verification.
@@ -750,5 +855,10 @@
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);
+
+BENCHMARK_CAPTURE(Triangle, Solid, FragShadeType::Solid, Multisample::False)->Unit(benchmark::kMillisecond);
+BENCHMARK_CAPTURE(Triangle, Interpolate, FragShadeType::Interpolate, Multisample::False)->Unit(benchmark::kMillisecond);
+BENCHMARK_CAPTURE(Triangle, Sample, FragShadeType::Sample, Multisample::False)->Unit(benchmark::kMillisecond);
+BENCHMARK_CAPTURE(Triangle, Solid_Multisample, FragShadeType::Solid, Multisample::True)->Unit(benchmark::kMillisecond);
+BENCHMARK_CAPTURE(Triangle, Interpolate_Multisample, FragShadeType::Interpolate, Multisample::True)->Unit(benchmark::kMillisecond);
+BENCHMARK_CAPTURE(Triangle, Sample_Multisample, FragShadeType::Sample, Multisample::True)->Unit(benchmark::kMillisecond);