// 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 #include template 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 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 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 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 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 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(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 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(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();