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/+/51889Tested-by: 's avatarAntonio Maiorano <amaiorano@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com>
parent 413f7cb1
...@@ -199,11 +199,25 @@ static void ClearImage(benchmark::State &state, vk::Format clearFormat, vk::Imag ...@@ -199,11 +199,25 @@ static void ClearImage(benchmark::State &state, vk::Format clearFormat, vk::Imag
} }
} }
enum class FragShadeType
{
Solid,
Interpolate,
Sample,
};
enum class Multisample
{
False,
True
};
class TriangleBenchmark : public VulkanBenchmark class TriangleBenchmark : public VulkanBenchmark
{ {
public: public:
TriangleBenchmark(bool multisample) TriangleBenchmark(FragShadeType fragShadeType, Multisample multisample)
: multisample(multisample) : fragShadeType(fragShadeType)
, multisample(multisample == Multisample::True)
{ {
window.reset(new Window(instance, windowSize)); window.reset(new Window(instance, windowSize));
swapchain.reset(new Swapchain(physicalDevice, device, *window)); swapchain.reset(new Swapchain(physicalDevice, device, *window));
...@@ -306,68 +320,72 @@ protected: ...@@ -306,68 +320,72 @@ protected:
commandPoolCreateInfo.flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer; commandPoolCreateInfo.flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer;
commandPool = device.createCommandPool(commandPoolCreateInfo); commandPool = device.createCommandPool(commandPoolCreateInfo);
texture.reset(new Image(device, 16, 16, vk::Format::eR8G8B8A8Unorm)); std::vector<vk::DescriptorSet> descriptorSets;
if(fragShadeType == FragShadeType::Sample)
// Fill texture with white {
vk::DeviceSize bufferSize = 16 * 16 * 4; texture.reset(new Image(device, 16, 16, vk::Format::eR8G8B8A8Unorm));
Buffer buffer(device, bufferSize, vk::BufferUsageFlagBits::eTransferSrc);
void *data = buffer.mapMemory(); // Fill texture with white
memset(data, 255, bufferSize); vk::DeviceSize bufferSize = 16 * 16 * 4;
buffer.unmapMemory(); Buffer buffer(device, bufferSize, vk::BufferUsageFlagBits::eTransferSrc);
void *data = buffer.mapMemory();
Util::transitionImageLayout(device, commandPool, queue, texture->getImage(), vk::Format::eR8G8B8A8Unorm, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal); memset(data, 255, bufferSize);
Util::copyBufferToImage(device, commandPool, queue, buffer.getBuffer(), texture->getImage(), 16, 16); buffer.unmapMemory();
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);
vk::SamplerCreateInfo samplerInfo; Util::copyBufferToImage(device, commandPool, queue, buffer.getBuffer(), texture->getImage(), 16, 16);
samplerInfo.magFilter = vk::Filter::eLinear; Util::transitionImageLayout(device, commandPool, queue, texture->getImage(), vk::Format::eR8G8B8A8Unorm, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal);
samplerInfo.minFilter = vk::Filter::eLinear;
samplerInfo.addressModeU = vk::SamplerAddressMode::eRepeat; vk::SamplerCreateInfo samplerInfo;
samplerInfo.addressModeV = vk::SamplerAddressMode::eRepeat; samplerInfo.magFilter = vk::Filter::eLinear;
samplerInfo.addressModeW = vk::SamplerAddressMode::eRepeat; samplerInfo.minFilter = vk::Filter::eLinear;
samplerInfo.anisotropyEnable = VK_FALSE; samplerInfo.addressModeU = vk::SamplerAddressMode::eRepeat;
samplerInfo.unnormalizedCoordinates = VK_FALSE; samplerInfo.addressModeV = vk::SamplerAddressMode::eRepeat;
samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear; samplerInfo.addressModeW = vk::SamplerAddressMode::eRepeat;
samplerInfo.mipLodBias = 0.0f; samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.minLod = 0.0f; samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.maxLod = 0.0f; samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear;
samplerInfo.mipLodBias = 0.0f;
sampler = device.createSampler(samplerInfo); samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 0.0f;
std::array<vk::DescriptorPoolSize, 1> poolSizes = {};
poolSizes[0].type = vk::DescriptorType::eCombinedImageSampler; sampler = device.createSampler(samplerInfo);
poolSizes[0].descriptorCount = 1;
std::array<vk::DescriptorPoolSize, 1> poolSizes = {};
vk::DescriptorPoolCreateInfo poolInfo; poolSizes[0].type = vk::DescriptorType::eCombinedImageSampler;
poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size()); poolSizes[0].descriptorCount = 1;
poolInfo.pPoolSizes = poolSizes.data();
poolInfo.maxSets = 1; vk::DescriptorPoolCreateInfo poolInfo;
poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
descriptorPool = device.createDescriptorPool(poolInfo); poolInfo.pPoolSizes = poolSizes.data();
poolInfo.maxSets = 1;
std::vector<vk::DescriptorSetLayout> layouts(1, descriptorSetLayout);
vk::DescriptorSetAllocateInfo allocInfo; descriptorPool = device.createDescriptorPool(poolInfo);
allocInfo.descriptorPool = descriptorPool;
allocInfo.descriptorSetCount = 1; std::vector<vk::DescriptorSetLayout> layouts(1, descriptorSetLayout);
allocInfo.pSetLayouts = layouts.data(); vk::DescriptorSetAllocateInfo allocInfo;
allocInfo.descriptorPool = descriptorPool;
std::vector<vk::DescriptorSet> descriptorSets = device.allocateDescriptorSets(allocInfo); allocInfo.descriptorSetCount = 1;
allocInfo.pSetLayouts = layouts.data();
vk::DescriptorImageInfo imageInfo;
imageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal; descriptorSets = device.allocateDescriptorSets(allocInfo);
imageInfo.imageView = texture->getImageView();
imageInfo.sampler = sampler; vk::DescriptorImageInfo imageInfo;
imageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
std::array<vk::WriteDescriptorSet, 1> descriptorWrites = {}; imageInfo.imageView = texture->getImageView();
imageInfo.sampler = sampler;
descriptorWrites[0].dstSet = descriptorSets[0];
descriptorWrites[0].dstBinding = 1; std::array<vk::WriteDescriptorSet, 1> descriptorWrites = {};
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = vk::DescriptorType::eCombinedImageSampler; descriptorWrites[0].dstSet = descriptorSets[0];
descriptorWrites[0].descriptorCount = 1; descriptorWrites[0].dstBinding = 1;
descriptorWrites[0].pImageInfo = &imageInfo; descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = vk::DescriptorType::eCombinedImageSampler;
device.updateDescriptorSets(static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr); descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pImageInfo = &imageInfo;
device.updateDescriptorSets(static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
}
vk::CommandBufferAllocateInfo commandBufferAllocateInfo; vk::CommandBufferAllocateInfo commandBufferAllocateInfo;
commandBufferAllocateInfo.commandPool = commandPool; commandBufferAllocateInfo.commandPool = commandPool;
...@@ -401,7 +419,10 @@ protected: ...@@ -401,7 +419,10 @@ protected:
vk::Rect2D scissor(vk::Offset2D(0, 0), windowSize); vk::Rect2D scissor(vk::Offset2D(0, 0), windowSize);
commandBuffers[i].setScissor(0, 1, &scissor); 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 // Draw a triangle
commandBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline); commandBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
...@@ -449,9 +470,26 @@ protected: ...@@ -449,9 +470,26 @@ protected:
vertices.inputBinding.stride = sizeof(Vertex); vertices.inputBinding.stride = sizeof(Vertex);
vertices.inputBinding.inputRate = vk::VertexInputRate::eVertex; vertices.inputBinding.inputRate = vk::VertexInputRate::eVertex;
vertices.inputAttributes.push_back(vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position))); switch(fragShadeType)
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))); 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.vertexBindingDescriptionCount = 1;
vertices.inputState.pVertexBindingDescriptions = &vertices.inputBinding; vertices.inputState.pVertexBindingDescriptions = &vertices.inputBinding;
...@@ -563,21 +601,25 @@ protected: ...@@ -563,21 +601,25 @@ protected:
vk::Pipeline createGraphicsPipeline(vk::RenderPass renderPass) vk::Pipeline createGraphicsPipeline(vk::RenderPass renderPass)
{ {
vk::DescriptorSetLayoutBinding samplerLayoutBinding; std::vector<vk::DescriptorSetLayout> setLayouts;
samplerLayoutBinding.binding = 1; if(fragShadeType == FragShadeType::Sample)
samplerLayoutBinding.descriptorCount = 1; {
samplerLayoutBinding.descriptorType = vk::DescriptorType::eCombinedImageSampler; vk::DescriptorSetLayoutBinding samplerLayoutBinding;
samplerLayoutBinding.pImmutableSamplers = nullptr; samplerLayoutBinding.binding = 1;
samplerLayoutBinding.stageFlags = vk::ShaderStageFlagBits::eFragment; samplerLayoutBinding.descriptorCount = 1;
samplerLayoutBinding.descriptorType = vk::DescriptorType::eCombinedImageSampler;
samplerLayoutBinding.pImmutableSamplers = nullptr;
samplerLayoutBinding.stageFlags = vk::ShaderStageFlagBits::eFragment;
std::array<vk::DescriptorSetLayoutBinding, 1> bindings = { samplerLayoutBinding }; std::array<vk::DescriptorSetLayoutBinding, 1> bindings = { samplerLayoutBinding };
vk::DescriptorSetLayoutCreateInfo layoutInfo; vk::DescriptorSetLayoutCreateInfo layoutInfo;
layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size()); layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
layoutInfo.pBindings = bindings.data(); 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; vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
pipelineLayoutCreateInfo.setLayoutCount = static_cast<uint32_t>(setLayouts.size()); pipelineLayoutCreateInfo.setLayoutCount = static_cast<uint32_t>(setLayouts.size());
...@@ -633,36 +675,98 @@ protected: ...@@ -633,36 +675,98 @@ protected:
multisampleState.rasterizationSamples = multisample ? vk::SampleCountFlagBits::e4 : vk::SampleCountFlagBits::e1; multisampleState.rasterizationSamples = multisample ? vk::SampleCountFlagBits::e4 : vk::SampleCountFlagBits::e1;
multisampleState.pSampleMask = nullptr; multisampleState.pSampleMask = nullptr;
const char *vertexShader = R"(#version 310 es const char *vertexShader = nullptr;
layout(location = 0) in vec3 inPos; const char *fragmentShader = nullptr;
layout(location = 1) in vec3 inColor;
layout(location = 0) out vec3 outColor; switch(fragShadeType)
layout(location = 1) out vec2 fragTexCoord; {
case FragShadeType::Solid:
void main()
{ {
outColor = inColor; vertexShader = R"(#version 310 es
gl_Position = vec4(inPos.xyz, 1.0); layout(location = 0) in vec3 inPos;
fragTexCoord = inPos.xy;
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;
case FragShadeType::Interpolate:
{
vertexShader = R"(#version 310 es
layout(location = 0) in vec3 inPos;
layout(location = 1) in vec3 inColor;
layout(location = 0) out vec3 outColor;
const char *fragmentShader = R"(#version 310 es void main()
precision highp float; {
outColor = inColor;
gl_Position = vec4(inPos.xyz, 1.0);
})";
layout(location = 0) in vec3 inColor; fragmentShader = R"(#version 310 es
layout(location = 1) in vec2 fragTexCoord; precision highp float;
layout(location = 0) out vec4 outColor; layout(location = 0) in vec3 inColor;
layout(binding = 0) uniform sampler2D texSampler; layout(location = 0) out vec4 outColor;
void main() void main()
{
outColor = vec4(inColor, 1.0);
})";
}
break;
case FragShadeType::Sample:
{ {
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;
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 vertexModule = createShaderModule(vertexShader, EShLanguage::EShLangVertex);
vk::ShaderModule fragmentModule = createShaderModule(fragmentShader, EShLanguage::EShLangFragment); vk::ShaderModule fragmentModule = createShaderModule(fragmentShader, EShLanguage::EShLangFragment);
...@@ -698,6 +802,7 @@ protected: ...@@ -698,6 +802,7 @@ protected:
} }
const vk::Extent2D windowSize = { 1280, 720 }; const vk::Extent2D windowSize = { 1280, 720 };
const FragShadeType fragShadeType;
const bool multisample; const bool multisample;
std::unique_ptr<Window> window; std::unique_ptr<Window> window;
...@@ -732,9 +837,9 @@ protected: ...@@ -732,9 +837,9 @@ protected:
std::vector<vk::CommandBuffer> commandBuffers; // Owning handles 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. if(false) benchmark.show(); // Enable for visual verification.
...@@ -750,5 +855,10 @@ static void Triangle(benchmark::State &state, bool multisample) ...@@ -750,5 +855,10 @@ static void Triangle(benchmark::State &state, bool multisample)
BENCHMARK_CAPTURE(ClearImage, VK_FORMAT_R8G8B8A8_UNORM, vk::Format::eR8G8B8A8Unorm, vk::ImageAspectFlagBits::eColor)->Unit(benchmark::kMillisecond); 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_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(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);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment