Make vk-unittests use VulkanWrapper

This change moves the VulkanBenchmark and DrawBenchmark classes to VulkanWrapper so that they can be used from other unit tests -- namely, vk-unittests. In doing so, it became clear that using these as base classes wasn't great for writing googletests, as text fixtures are classes themselves, and this resulted in messy multiple inheritance. So I modified the two classes to use callback registration instead of virtual functions. Apart from reworking existing tests (e.g. see TriangleBenchmark.cpp), I also added a new DrawTests.cpp to vk-unittests with a unit test to make sure we don't crash when leaving out "gl_Position", a bug that sugoi@ fixed in swiftshader-cl/51808. This is a good example of how easy it can be to write such unit tests now. List of changes: * Moved VulkanBenchmark and DrawBenchmark to VulkanWrapper, and renamed VulkanTester and DrawTester respectively. * ClearImageBenchmark refactored to aggregate a VulkanTester. This is an example where using a class is fine as we can still use the testers via aggregation. * TriangleBenchmark tests refactored to use DrawTester and register callbacks. * Moved compute tests to a ComputeTests.cpp. * Moved the other tests to BasicTests.cpp. * Added DrawTests.cpp with new DrawTests.VertexShaderNoPositionOutput test. * CMake: add VulkanWrapper target for unittests as well as benchmarks. * CMake: change FOLDER to better organize the tests and benchmarks for VS. Bug: b/176981107 Change-Id: Ib1a0b85b3df787d2e39da08930414f9a14954a73 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/52348 Kokoro-Result: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Tested-by: 's avatarAntonio Maiorano <amaiorano@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com>
parent 266614a3
...@@ -243,13 +243,20 @@ function(InitSubmodule target submodule_dir) ...@@ -243,13 +243,20 @@ function(InitSubmodule target submodule_dir)
endif() endif()
endfunction() endfunction()
if (SWIFTSHADER_BUILD_TESTS OR SWIFTSHADER_BUILD_BENCHMARKS)
set(BUILD_VULKAN_WRAPPER TRUE)
endif()
if (BUILD_VULKAN_WRAPPER)
InitSubmodule(glslang ${THIRD_PARTY_DIR}/glslang)
endif()
if (SWIFTSHADER_BUILD_TESTS) if (SWIFTSHADER_BUILD_TESTS)
InitSubmodule(gtest ${THIRD_PARTY_DIR}/googletest) InitSubmodule(gtest ${THIRD_PARTY_DIR}/googletest)
endif() endif()
if(SWIFTSHADER_BUILD_BENCHMARKS) if(SWIFTSHADER_BUILD_BENCHMARKS)
InitSubmodule(benchmark::benchmark ${THIRD_PARTY_DIR}/benchmark) InitSubmodule(benchmark::benchmark ${THIRD_PARTY_DIR}/benchmark)
InitSubmodule(glslang ${THIRD_PARTY_DIR}/glslang)
endif() endif()
if(REACTOR_EMIT_DEBUG_INFO) if(REACTOR_EMIT_DEBUG_INFO)
...@@ -992,6 +999,13 @@ if(HAVE_PVR_SUBMODULE AND SWIFTSHADER_BUILD_PVR) ...@@ -992,6 +999,13 @@ if(HAVE_PVR_SUBMODULE AND SWIFTSHADER_BUILD_PVR)
endif() endif()
endif() endif()
if(BUILD_VULKAN_WRAPPER)
if (NOT TARGET glslang)
add_subdirectory(${THIRD_PARTY_DIR}/glslang)
endif()
add_subdirectory(${TESTS_DIR}/VulkanWrapper) # Add VulkanWrapper target
endif()
if(SWIFTSHADER_BUILD_TESTS) if(SWIFTSHADER_BUILD_TESTS)
add_subdirectory(${TESTS_DIR}/ReactorUnitTests) # Add ReactorUnitTests target add_subdirectory(${TESTS_DIR}/ReactorUnitTests) # Add ReactorUnitTests target
add_subdirectory(${TESTS_DIR}/GLESUnitTests) # Add gles-unittests target add_subdirectory(${TESTS_DIR}/GLESUnitTests) # Add gles-unittests target
...@@ -1000,11 +1014,6 @@ if(SWIFTSHADER_BUILD_TESTS) ...@@ -1000,11 +1014,6 @@ if(SWIFTSHADER_BUILD_TESTS)
endif() endif()
if(SWIFTSHADER_BUILD_BENCHMARKS) if(SWIFTSHADER_BUILD_BENCHMARKS)
if (NOT TARGET glslang)
add_subdirectory(${THIRD_PARTY_DIR}/glslang)
endif()
add_subdirectory(${TESTS_DIR}/VulkanWrapper) # Add VulkanWrapper target
if (NOT TARGET benchmark::benchmark) if (NOT TARGET benchmark::benchmark)
set(BENCHMARK_ENABLE_TESTING FALSE CACHE BOOL FALSE FORCE) set(BENCHMARK_ENABLE_TESTING FALSE CACHE BOOL FALSE FORCE)
add_subdirectory(${THIRD_PARTY_DIR}/benchmark) add_subdirectory(${THIRD_PARTY_DIR}/benchmark)
......
...@@ -31,7 +31,7 @@ add_executable(ReactorBenchmarks ...@@ -31,7 +31,7 @@ add_executable(ReactorBenchmarks
) )
set_target_properties(ReactorBenchmarks PROPERTIES set_target_properties(ReactorBenchmarks PROPERTIES
FOLDER "Benchmarks" FOLDER "Tests/Benchmarks"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
) )
......
...@@ -32,7 +32,7 @@ add_executable(system-benchmarks ...@@ -32,7 +32,7 @@ add_executable(system-benchmarks
) )
set_target_properties(system-benchmarks PROPERTIES set_target_properties(system-benchmarks PROPERTIES
FOLDER "Benchmarks" FOLDER "Tests/Benchmarks"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
) )
......
...@@ -23,12 +23,8 @@ set(ROOT_PROJECT_LINK_LIBRARIES ...@@ -23,12 +23,8 @@ set(ROOT_PROJECT_LINK_LIBRARIES
set(VULKAN_BENCHMARKS_SRC_FILES set(VULKAN_BENCHMARKS_SRC_FILES
ClearImageBenchmarks.cpp ClearImageBenchmarks.cpp
DrawBenchmark.cpp
DrawBenchmark.hpp
main.cpp main.cpp
TriangleBenchmarks.cpp TriangleBenchmarks.cpp
VulkanBenchmark.cpp
VulkanBenchmark.hpp
) )
add_executable(VulkanBenchmarks add_executable(VulkanBenchmarks
...@@ -48,7 +44,7 @@ add_dependencies(VulkanBenchmarks ...@@ -48,7 +44,7 @@ add_dependencies(VulkanBenchmarks
) )
set_target_properties(VulkanBenchmarks PROPERTIES set_target_properties(VulkanBenchmarks PROPERTIES
FOLDER "Benchmarks" FOLDER "Tests/Benchmarks"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
) )
......
...@@ -12,17 +12,18 @@ ...@@ -12,17 +12,18 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "VulkanBenchmark.hpp" #include "VulkanTester.hpp"
#include "benchmark/benchmark.h" #include "benchmark/benchmark.h"
#include <cassert> #include <cassert>
class ClearImageBenchmark : public VulkanBenchmark class ClearImageBenchmark
{ {
public: public:
void initialize(vk::Format clearFormat, vk::ImageAspectFlagBits clearAspect) void initialize(vk::Format clearFormat, vk::ImageAspectFlagBits clearAspect)
{ {
VulkanBenchmark::initialize(); tester.initialize();
auto &device = tester.getDevice();
vk::ImageCreateInfo imageInfo; vk::ImageCreateInfo imageInfo;
imageInfo.imageType = vk::ImageType::e2D; imageInfo.imageType = vk::ImageType::e2D;
...@@ -48,7 +49,7 @@ public: ...@@ -48,7 +49,7 @@ public:
device.bindImageMemory(image, memory, 0); device.bindImageMemory(image, memory, 0);
vk::CommandPoolCreateInfo commandPoolCreateInfo; vk::CommandPoolCreateInfo commandPoolCreateInfo;
commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex; commandPoolCreateInfo.queueFamilyIndex = tester.getQueueFamilyIndex();
commandPool = device.createCommandPool(commandPoolCreateInfo); commandPool = device.createCommandPool(commandPoolCreateInfo);
...@@ -96,6 +97,7 @@ public: ...@@ -96,6 +97,7 @@ public:
~ClearImageBenchmark() ~ClearImageBenchmark()
{ {
auto &device = tester.getDevice();
device.freeCommandBuffers(commandPool, 1, &commandBuffer); device.freeCommandBuffers(commandPool, 1, &commandBuffer);
device.destroyCommandPool(commandPool, nullptr); device.destroyCommandPool(commandPool, nullptr);
device.freeMemory(memory, nullptr); device.freeMemory(memory, nullptr);
...@@ -104,6 +106,8 @@ public: ...@@ -104,6 +106,8 @@ public:
void clear() void clear()
{ {
auto &queue = tester.getQueue();
vk::SubmitInfo submitInfo; vk::SubmitInfo submitInfo;
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer; submitInfo.pCommandBuffers = &commandBuffer;
...@@ -113,6 +117,7 @@ public: ...@@ -113,6 +117,7 @@ public:
} }
private: private:
VulkanTester tester;
vk::Image image; // Owning handle vk::Image image; // Owning handle
vk::DeviceMemory memory; // Owning handle vk::DeviceMemory memory; // Owning handle
vk::CommandPool commandPool; // Owning handle vk::CommandPool commandPool; // Owning handle
......
...@@ -13,22 +13,33 @@ ...@@ -13,22 +13,33 @@
// limitations under the License. // limitations under the License.
#include "Buffer.hpp" #include "Buffer.hpp"
#include "DrawBenchmark.hpp" #include "DrawTester.hpp"
#include "benchmark/benchmark.h" #include "benchmark/benchmark.h"
#include <cassert> #include <cassert>
#include <vector> #include <vector>
class TriangleSolidColorBenchmark : public DrawBenchmark template<typename T>
static void RunBenchmark(benchmark::State &state, T &tester)
{ {
public: tester.initialize();
TriangleSolidColorBenchmark(Multisample multisample)
: DrawBenchmark(multisample) if(false) tester.show(); // Enable for visual verification.
{}
// Warmup
tester.renderFrame();
protected: for(auto _ : state)
void doCreateVertexBuffers() override
{ {
tester.renderFrame();
}
}
static void TriangleSolidColor(benchmark::State &state, Multisample multisample)
{
DrawTester tester(multisample);
tester.onCreateVertexBuffers([](DrawTester &tester) {
struct Vertex struct Vertex
{ {
float position[3]; float position[3];
...@@ -43,11 +54,10 @@ protected: ...@@ -43,11 +54,10 @@ protected:
std::vector<vk::VertexInputAttributeDescription> inputAttributes; std::vector<vk::VertexInputAttributeDescription> inputAttributes;
inputAttributes.push_back(vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position))); inputAttributes.push_back(vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position)));
addVertexBuffer(vertexBufferData, sizeof(vertexBufferData), std::move(inputAttributes)); tester.addVertexBuffer(vertexBufferData, sizeof(vertexBufferData), std::move(inputAttributes));
} });
vk::ShaderModule doCreateVertexShader() override tester.onCreateVertexShader([](DrawTester &tester) {
{
const char *vertexShader = R"(#version 310 es const char *vertexShader = R"(#version 310 es
layout(location = 0) in vec3 inPos; layout(location = 0) in vec3 inPos;
...@@ -56,11 +66,10 @@ protected: ...@@ -56,11 +66,10 @@ protected:
gl_Position = vec4(inPos.xyz, 1.0); gl_Position = vec4(inPos.xyz, 1.0);
})"; })";
return createShaderModule(vertexShader, EShLanguage::EShLangVertex); return tester.createShaderModule(vertexShader, EShLanguage::EShLangVertex);
} });
vk::ShaderModule doCreateFragmentShader() override tester.onCreateFragmentShader([](DrawTester &tester) {
{
const char *fragmentShader = R"(#version 310 es const char *fragmentShader = R"(#version 310 es
precision highp float; precision highp float;
...@@ -71,20 +80,17 @@ protected: ...@@ -71,20 +80,17 @@ protected:
outColor = vec4(1.0, 1.0, 1.0, 1.0); outColor = vec4(1.0, 1.0, 1.0, 1.0);
})"; })";
return createShaderModule(fragmentShader, EShLanguage::EShLangFragment); return tester.createShaderModule(fragmentShader, EShLanguage::EShLangFragment);
} });
};
RunBenchmark(state, tester);
}
class TriangleInterpolateColorBenchmark : public DrawBenchmark static void TriangleInterpolateColor(benchmark::State &state, Multisample multisample)
{ {
public: DrawTester tester(multisample);
TriangleInterpolateColorBenchmark(Multisample multisample)
: DrawBenchmark(multisample)
{}
protected: tester.onCreateVertexBuffers([](DrawTester &tester) {
void doCreateVertexBuffers() override
{
struct Vertex struct Vertex
{ {
float position[3]; float position[3];
...@@ -101,11 +107,10 @@ protected: ...@@ -101,11 +107,10 @@ protected:
inputAttributes.push_back(vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position))); 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))); inputAttributes.push_back(vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, color)));
addVertexBuffer(vertexBufferData, sizeof(vertexBufferData), std::move(inputAttributes)); tester.addVertexBuffer(vertexBufferData, sizeof(vertexBufferData), std::move(inputAttributes));
} });
vk::ShaderModule doCreateVertexShader() override tester.onCreateVertexShader([](DrawTester &tester) {
{
const char *vertexShader = R"(#version 310 es const char *vertexShader = R"(#version 310 es
layout(location = 0) in vec3 inPos; layout(location = 0) in vec3 inPos;
layout(location = 1) in vec3 inColor; layout(location = 1) in vec3 inColor;
...@@ -118,11 +123,10 @@ protected: ...@@ -118,11 +123,10 @@ protected:
gl_Position = vec4(inPos.xyz, 1.0); gl_Position = vec4(inPos.xyz, 1.0);
})"; })";
return createShaderModule(vertexShader, EShLanguage::EShLangVertex); return tester.createShaderModule(vertexShader, EShLanguage::EShLangVertex);
} });
vk::ShaderModule doCreateFragmentShader() override tester.onCreateFragmentShader([](DrawTester &tester) {
{
const char *fragmentShader = R"(#version 310 es const char *fragmentShader = R"(#version 310 es
precision highp float; precision highp float;
...@@ -135,20 +139,17 @@ protected: ...@@ -135,20 +139,17 @@ protected:
outColor = vec4(inColor, 1.0); outColor = vec4(inColor, 1.0);
})"; })";
return createShaderModule(fragmentShader, EShLanguage::EShLangFragment); return tester.createShaderModule(fragmentShader, EShLanguage::EShLangFragment);
} });
};
RunBenchmark(state, tester);
}
class TriangleSampleTextureBenchmark : public DrawBenchmark static void TriangleSampleTexture(benchmark::State &state, Multisample multisample)
{ {
public: DrawTester tester(multisample);
TriangleSampleTextureBenchmark(Multisample multisample)
: DrawBenchmark(multisample)
{}
protected: tester.onCreateVertexBuffers([](DrawTester &tester) {
void doCreateVertexBuffers() override
{
struct Vertex struct Vertex
{ {
float position[3]; float position[3];
...@@ -167,11 +168,10 @@ protected: ...@@ -167,11 +168,10 @@ protected:
inputAttributes.push_back(vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, color))); inputAttributes.push_back(vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, color)));
inputAttributes.push_back(vk::VertexInputAttributeDescription(2, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, texCoord))); inputAttributes.push_back(vk::VertexInputAttributeDescription(2, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, texCoord)));
addVertexBuffer(vertexBufferData, sizeof(vertexBufferData), std::move(inputAttributes)); tester.addVertexBuffer(vertexBufferData, sizeof(vertexBufferData), std::move(inputAttributes));
} });
vk::ShaderModule doCreateVertexShader() override tester.onCreateVertexShader([](DrawTester &tester) {
{
const char *vertexShader = R"(#version 310 es const char *vertexShader = R"(#version 310 es
layout(location = 0) in vec3 inPos; layout(location = 0) in vec3 inPos;
layout(location = 1) in vec3 inColor; layout(location = 1) in vec3 inColor;
...@@ -186,11 +186,10 @@ protected: ...@@ -186,11 +186,10 @@ protected:
fragTexCoord = inPos.xy; fragTexCoord = inPos.xy;
})"; })";
return createShaderModule(vertexShader, EShLanguage::EShLangVertex); return tester.createShaderModule(vertexShader, EShLanguage::EShLangVertex);
} });
vk::ShaderModule doCreateFragmentShader() override tester.onCreateFragmentShader([](DrawTester &tester) {
{
const char *fragmentShader = R"(#version 310 es const char *fragmentShader = R"(#version 310 es
precision highp float; precision highp float;
...@@ -206,11 +205,10 @@ protected: ...@@ -206,11 +205,10 @@ protected:
outColor = texture(texSampler, fragTexCoord) * vec4(inColor, 1.0); outColor = texture(texSampler, fragTexCoord) * vec4(inColor, 1.0);
})"; })";
return createShaderModule(fragmentShader, EShLanguage::EShLangFragment); return tester.createShaderModule(fragmentShader, EShLanguage::EShLangFragment);
} });
std::vector<vk::DescriptorSetLayoutBinding> doCreateDescriptorSetLayouts() override tester.onCreateDescriptorSetLayouts([](DrawTester &tester) -> std::vector<vk::DescriptorSetLayoutBinding> {
{
vk::DescriptorSetLayoutBinding samplerLayoutBinding; vk::DescriptorSetLayoutBinding samplerLayoutBinding;
samplerLayoutBinding.binding = 1; samplerLayoutBinding.binding = 1;
samplerLayoutBinding.descriptorCount = 1; samplerLayoutBinding.descriptorCount = 1;
...@@ -219,11 +217,13 @@ protected: ...@@ -219,11 +217,13 @@ protected:
samplerLayoutBinding.stageFlags = vk::ShaderStageFlagBits::eFragment; samplerLayoutBinding.stageFlags = vk::ShaderStageFlagBits::eFragment;
return { samplerLayoutBinding }; return { samplerLayoutBinding };
} });
void doUpdateDescriptorSet(vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet) override tester.onUpdateDescriptorSet([](DrawTester &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet) {
{ auto &device = tester.getDevice();
auto &texture = addImage(device, 16, 16, vk::Format::eR8G8B8A8Unorm).obj; auto &queue = tester.getQueue();
auto &texture = tester.addImage(device, 16, 16, vk::Format::eR8G8B8A8Unorm).obj;
// Fill texture with white // Fill texture with white
vk::DeviceSize bufferSize = 16 * 16 * 4; vk::DeviceSize bufferSize = 16 * 16 * 4;
...@@ -249,7 +249,7 @@ protected: ...@@ -249,7 +249,7 @@ protected:
samplerInfo.minLod = 0.0f; samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 0.0f; samplerInfo.maxLod = 0.0f;
auto sampler = addSampler(samplerInfo); auto sampler = tester.addSampler(samplerInfo);
vk::DescriptorImageInfo imageInfo; vk::DescriptorImageInfo imageInfo;
imageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal; imageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
...@@ -266,41 +266,9 @@ protected: ...@@ -266,41 +266,9 @@ protected:
descriptorWrites[0].pImageInfo = &imageInfo; 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);
} });
};
template<typename T>
static void RunBenchmark(benchmark::State &state, T &benchmark)
{
benchmark.initialize();
if(false) benchmark.show(); // Enable for visual verification.
// Warmup
benchmark.renderFrame();
for(auto _ : state) RunBenchmark(state, tester);
{
benchmark.renderFrame();
}
}
static void TriangleSolidColor(benchmark::State &state, Multisample multisample)
{
TriangleSolidColorBenchmark benchmark(multisample);
RunBenchmark(state, benchmark);
}
static void TriangleInterpolateColor(benchmark::State &state, Multisample multisample)
{
TriangleInterpolateColorBenchmark benchmark(multisample);
RunBenchmark(state, benchmark);
}
static void TriangleSampleTexture(benchmark::State &state, Multisample multisample)
{
TriangleSampleTextureBenchmark benchmark(multisample);
RunBenchmark(state, benchmark);
} }
BENCHMARK_CAPTURE(TriangleSolidColor, TriangleSolidColor, Multisample::False)->Unit(benchmark::kMillisecond); BENCHMARK_CAPTURE(TriangleSolidColor, TriangleSolidColor, Multisample::False)->Unit(benchmark::kMillisecond);
......
// 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 "VulkanBenchmark.hpp"
VulkanBenchmark::~VulkanBenchmark()
{
device.waitIdle();
device.destroy(nullptr);
instance.destroy(nullptr);
}
void VulkanBenchmark::initialize()
{
// TODO(b/158231104): Other platforms
#if defined(_WIN32)
dl = std::make_unique<vk::DynamicLoader>("./vk_swiftshader.dll");
#elif defined(__linux__)
dl = std::make_unique<vk::DynamicLoader>("./libvk_swiftshader.so");
#else
# error Unimplemented platform
#endif
assert(dl->success());
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl->getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
instance = vk::createInstance({}, nullptr);
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance);
std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
assert(!physicalDevices.empty());
physicalDevice = physicalDevices[0];
const float defaultQueuePriority = 0.0f;
vk::DeviceQueueCreateInfo queueCreatInfo;
queueCreatInfo.queueFamilyIndex = queueFamilyIndex;
queueCreatInfo.queueCount = 1;
queueCreatInfo.pQueuePriorities = &defaultQueuePriority;
vk::DeviceCreateInfo deviceCreateInfo;
deviceCreateInfo.queueCreateInfoCount = 1;
deviceCreateInfo.pQueueCreateInfos = &queueCreatInfo;
device = physicalDevice.createDevice(deviceCreateInfo, nullptr);
queue = device.getQueue(queueFamilyIndex, 0);
}
...@@ -26,9 +26,12 @@ test("swiftshader_vulkan_unittests") { ...@@ -26,9 +26,12 @@ test("swiftshader_vulkan_unittests") {
sources = [ sources = [
"//gpu/swiftshader_tests_main.cc", "//gpu/swiftshader_tests_main.cc",
"Device.cpp", "BasicTests.cpp"
"Driver.cpp", "ComputeTests.cpp"
"unittests.cpp", "Device.cpp"
"DrawTests.cpp"
"Driver.cpp"
"main.cpp"
] ]
include_dirs = [ include_dirs = [
......
// Copyright 2018 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.
// Vulkan unit tests that provide coverage for functionality not tested by
// the dEQP test suite. Also used as a smoke test.
#include "Device.hpp"
#include "Driver.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
class BasicTest : public testing::Test
{
protected:
static Driver driver;
void SetUp() override
{
ASSERT_TRUE(driver.loadSwiftShader());
}
void TearDown() override
{
driver.unload();
}
};
Driver BasicTest::driver;
TEST_F(BasicTest, ICD_Check)
{
auto createInstance = driver.vk_icdGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateInstance");
EXPECT_NE(createInstance, nullptr);
auto enumerateInstanceExtensionProperties =
driver.vk_icdGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
EXPECT_NE(enumerateInstanceExtensionProperties, nullptr);
auto enumerateInstanceLayerProperties =
driver.vk_icdGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceLayerProperties");
EXPECT_NE(enumerateInstanceLayerProperties, nullptr);
auto enumerateInstanceVersion = driver.vk_icdGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion");
EXPECT_NE(enumerateInstanceVersion, nullptr);
auto bad_function = driver.vk_icdGetInstanceProcAddr(VK_NULL_HANDLE, "bad_function");
EXPECT_EQ(bad_function, nullptr);
}
TEST_F(BasicTest, Version)
{
uint32_t apiVersion = 0;
VkResult result = driver.vkEnumerateInstanceVersion(&apiVersion);
EXPECT_EQ(apiVersion, (uint32_t)VK_API_VERSION_1_1);
const VkInstanceCreateInfo createInfo = {
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
nullptr, // pNext
0, // flags
nullptr, // pApplicationInfo
0, // enabledLayerCount
nullptr, // ppEnabledLayerNames
0, // enabledExtensionCount
nullptr, // ppEnabledExtensionNames
};
VkInstance instance = VK_NULL_HANDLE;
result = driver.vkCreateInstance(&createInfo, nullptr, &instance);
EXPECT_EQ(result, VK_SUCCESS);
ASSERT_TRUE(driver.resolve(instance));
uint32_t pPhysicalDeviceCount = 0;
result = driver.vkEnumeratePhysicalDevices(instance, &pPhysicalDeviceCount, nullptr);
EXPECT_EQ(result, VK_SUCCESS);
EXPECT_EQ(pPhysicalDeviceCount, 1U);
VkPhysicalDevice pPhysicalDevice = VK_NULL_HANDLE;
result = driver.vkEnumeratePhysicalDevices(instance, &pPhysicalDeviceCount, &pPhysicalDevice);
EXPECT_EQ(result, VK_SUCCESS);
EXPECT_NE(pPhysicalDevice, (VkPhysicalDevice)VK_NULL_HANDLE);
VkPhysicalDeviceProperties physicalDeviceProperties;
driver.vkGetPhysicalDeviceProperties(pPhysicalDevice, &physicalDeviceProperties);
EXPECT_EQ(physicalDeviceProperties.apiVersion, (uint32_t)VK_API_VERSION_1_1);
EXPECT_EQ(physicalDeviceProperties.deviceID, 0xC0DEU);
EXPECT_EQ(physicalDeviceProperties.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
EXPECT_NE(strstr(physicalDeviceProperties.deviceName, "SwiftShader Device"), nullptr);
VkPhysicalDeviceProperties2 physicalDeviceProperties2;
VkPhysicalDeviceDriverPropertiesKHR physicalDeviceDriverProperties;
physicalDeviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
physicalDeviceProperties2.pNext = &physicalDeviceDriverProperties;
physicalDeviceDriverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
physicalDeviceDriverProperties.pNext = nullptr;
physicalDeviceDriverProperties.driverID = (VkDriverIdKHR)0;
driver.vkGetPhysicalDeviceProperties2(pPhysicalDevice, &physicalDeviceProperties2);
EXPECT_EQ(physicalDeviceDriverProperties.driverID, VK_DRIVER_ID_GOOGLE_SWIFTSHADER_KHR);
driver.vkDestroyInstance(instance, nullptr);
}
/*
TEST_F(BasicTest, UnsupportedDeviceExtension_DISABLED)
{
uint32_t apiVersion = 0;
VkResult result = driver.vkEnumerateInstanceVersion(&apiVersion);
EXPECT_EQ(apiVersion, (uint32_t)VK_API_VERSION_1_1);
const VkInstanceCreateInfo createInfo = {
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
nullptr, // pNext
0, // flags
nullptr, // pApplicationInfo
0, // enabledLayerCount
nullptr, // ppEnabledLayerNames
0, // enabledExtensionCount
nullptr, // ppEnabledExtensionNames
};
VkInstance instance = VK_NULL_HANDLE;
result = driver.vkCreateInstance(&createInfo, nullptr, &instance);
EXPECT_EQ(result, VK_SUCCESS);
ASSERT_TRUE(driver.resolve(instance));
VkBaseInStructure unsupportedExt = { VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT, nullptr };
// Gather all physical devices
std::vector<VkPhysicalDevice> physicalDevices;
result = Device::GetPhysicalDevices(&driver, instance, physicalDevices);
EXPECT_EQ(result, VK_SUCCESS);
// Inspect each physical device's queue families for compute support.
for(auto physicalDevice : physicalDevices)
{
int queueFamilyIndex = Device::GetComputeQueueFamilyIndex(&driver, physicalDevice);
if(queueFamilyIndex < 0)
{
continue;
}
const float queuePrioritory = 1.0f;
const VkDeviceQueueCreateInfo deviceQueueCreateInfo = {
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
nullptr, // pNext
0, // flags
(uint32_t)queueFamilyIndex, // queueFamilyIndex
1, // queueCount
&queuePrioritory, // pQueuePriorities
};
const VkDeviceCreateInfo deviceCreateInfo = {
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
&unsupportedExt, // pNext
0, // flags
1, // queueCreateInfoCount
&deviceQueueCreateInfo, // pQueueCreateInfos
0, // enabledLayerCount
nullptr, // ppEnabledLayerNames
0, // enabledExtensionCount
nullptr, // ppEnabledExtensionNames
nullptr, // pEnabledFeatures
};
VkDevice device;
result = driver.vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device);
EXPECT_EQ(result, VK_SUCCESS);
driver.vkDestroyDevice(device, nullptr);
}
driver.vkDestroyInstance(instance, nullptr);
}
*/
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
# limitations under the License. # limitations under the License.
set(ROOT_PROJECT_COMPILE_OPTIONS set(ROOT_PROJECT_COMPILE_OPTIONS
${SWIFTSHADER_COMPILE_OPTIONS}
${WARNINGS_AS_ERRORS} ${WARNINGS_AS_ERRORS}
) )
...@@ -23,14 +22,16 @@ set(ROOT_PROJECT_LINK_LIBRARIES ...@@ -23,14 +22,16 @@ set(ROOT_PROJECT_LINK_LIBRARIES
) )
set(VULKAN_UNIT_TESTS_SRC_FILES set(VULKAN_UNIT_TESTS_SRC_FILES
BasicTests.cpp
ComputeTests.cpp
Device.cpp
Device.hpp Device.hpp
DrawTests.cpp
Driver.cpp
Driver.hpp Driver.hpp
main.cpp
VkGlobalFuncs.hpp VkGlobalFuncs.hpp
VkInstanceFuncs.hpp VkInstanceFuncs.hpp
Device.cpp
Driver.cpp
main.cpp
unittests.cpp
) )
add_executable(vk-unittests add_executable(vk-unittests
...@@ -72,5 +73,6 @@ target_link_libraries(vk-unittests ...@@ -72,5 +73,6 @@ target_link_libraries(vk-unittests
gtest gtest
gmock gmock
SPIRV-Tools SPIRV-Tools
VulkanWrapper
${ROOT_PROJECT_LINK_LIBRARIES} ${ROOT_PROJECT_LINK_LIBRARIES}
) )
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -333,7 +333,7 @@ void Device::UpdateStorageBufferDescriptorSets( ...@@ -333,7 +333,7 @@ void Device::UpdateStorageBufferDescriptorSets(
}); });
} }
driver->vkUpdateDescriptorSets(device, writes.size(), writes.data(), 0, nullptr); driver->vkUpdateDescriptorSets(device, (uint32_t)writes.size(), writes.data(), 0, nullptr);
} }
VkResult Device::AllocateMemory(size_t size, VkMemoryPropertyFlags flags, VkDeviceMemory *out) const VkResult Device::AllocateMemory(size_t size, VkMemoryPropertyFlags flags, VkDeviceMemory *out) const
......
// 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 "DrawTester.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
class DrawTest : public testing::Test
{
};
// Test that a vertex shader with no gl_Position works.
// This was fixed in swiftshader-cl/51808
TEST_F(DrawTest, VertexShaderNoPositionOutput)
{
DrawTester tester;
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()
{
// Remove gl_Position on purpose for the test
//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);
});
tester.initialize();
tester.renderFrame();
}
...@@ -17,20 +17,24 @@ set(ROOT_PROJECT_COMPILE_OPTIONS ...@@ -17,20 +17,24 @@ set(ROOT_PROJECT_COMPILE_OPTIONS
) )
set(VULKAN_WRAPPER_SRC_FILES set(VULKAN_WRAPPER_SRC_FILES
Buffer.hpp
Framebuffer.hpp
Image.hpp
Swapchain.hpp
Util.hpp
VulkanHeaders.hpp
Window.hpp
Buffer.cpp Buffer.cpp
Buffer.hpp
DrawTester.cpp
DrawTester.hpp
Framebuffer.cpp Framebuffer.cpp
Framebuffer.hpp
Image.cpp Image.cpp
Image.hpp
Swapchain.cpp Swapchain.cpp
Swapchain.hpp
Util.cpp Util.cpp
Util.hpp
VulkanHeaders.cpp VulkanHeaders.cpp
VulkanHeaders.hpp
VulkanTester.cpp
VulkanTester.hpp
Window.cpp Window.cpp
Window.hpp
) )
add_library(VulkanWrapper STATIC add_library(VulkanWrapper STATIC
...@@ -50,7 +54,7 @@ if (NOT TARGET SPIRV) ...@@ -50,7 +54,7 @@ if (NOT TARGET SPIRV)
endif() endif()
set_target_properties(VulkanWrapper PROPERTIES set_target_properties(VulkanWrapper PROPERTIES
FOLDER "Benchmarks" FOLDER "Tests"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
) )
...@@ -60,6 +64,11 @@ target_include_directories(VulkanWrapper ...@@ -60,6 +64,11 @@ target_include_directories(VulkanWrapper
"${SWIFTSHADER_DIR}/include" "${SWIFTSHADER_DIR}/include"
) )
target_compile_definitions(VulkanWrapper
PUBLIC
"STANDALONE"
)
target_compile_options(VulkanWrapper target_compile_options(VulkanWrapper
PRIVATE PRIVATE
${ROOT_PROJECT_COMPILE_OPTIONS} ${ROOT_PROJECT_COMPILE_OPTIONS}
......
...@@ -12,16 +12,16 @@ ...@@ -12,16 +12,16 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "DrawBenchmark.hpp" #include "DrawTester.hpp"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
DrawBenchmark::DrawBenchmark(Multisample multisample) DrawTester::DrawTester(Multisample multisample)
: multisample(multisample == Multisample::True) : multisample(multisample == Multisample::True)
{ {
} }
DrawBenchmark::~DrawBenchmark() DrawTester::~DrawTester()
{ {
device.freeCommandBuffers(commandPool, commandBuffers); device.freeCommandBuffers(commandPool, commandBuffers);
...@@ -59,9 +59,9 @@ DrawBenchmark::~DrawBenchmark() ...@@ -59,9 +59,9 @@ DrawBenchmark::~DrawBenchmark()
window.reset(); window.reset();
} }
void DrawBenchmark::initialize() void DrawTester::initialize()
{ {
VulkanBenchmark::initialize(); VulkanTester::initialize();
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));
...@@ -78,7 +78,7 @@ void DrawBenchmark::initialize() ...@@ -78,7 +78,7 @@ void DrawBenchmark::initialize()
createCommandBuffers(renderPass); createCommandBuffers(renderPass);
} }
void DrawBenchmark::renderFrame() void DrawTester::renderFrame()
{ {
swapchain->acquireNextImage(presentCompleteSemaphore, currentFrameBuffer); swapchain->acquireNextImage(presentCompleteSemaphore, currentFrameBuffer);
...@@ -101,12 +101,12 @@ void DrawBenchmark::renderFrame() ...@@ -101,12 +101,12 @@ void DrawBenchmark::renderFrame()
swapchain->queuePresent(queue, currentFrameBuffer, renderCompleteSemaphore); swapchain->queuePresent(queue, currentFrameBuffer, renderCompleteSemaphore);
} }
void DrawBenchmark::show() void DrawTester::show()
{ {
window->show(); window->show();
} }
vk::RenderPass DrawBenchmark::createRenderPass(vk::Format colorFormat) vk::RenderPass DrawTester::createRenderPass(vk::Format colorFormat)
{ {
std::vector<vk::AttachmentDescription> attachments(multisample ? 2 : 1); std::vector<vk::AttachmentDescription> attachments(multisample ? 2 : 1);
...@@ -187,7 +187,7 @@ vk::RenderPass DrawBenchmark::createRenderPass(vk::Format colorFormat) ...@@ -187,7 +187,7 @@ vk::RenderPass DrawBenchmark::createRenderPass(vk::Format colorFormat)
return device.createRenderPass(renderPassInfo); return device.createRenderPass(renderPassInfo);
} }
void DrawBenchmark::createFramebuffers(vk::RenderPass renderPass) void DrawTester::createFramebuffers(vk::RenderPass renderPass)
{ {
framebuffers.resize(swapchain->imageCount()); framebuffers.resize(swapchain->imageCount());
...@@ -197,14 +197,14 @@ void DrawBenchmark::createFramebuffers(vk::RenderPass renderPass) ...@@ -197,14 +197,14 @@ void DrawBenchmark::createFramebuffers(vk::RenderPass renderPass)
} }
} }
void DrawBenchmark::prepareVertices() void DrawTester::prepareVertices()
{ {
doCreateVertexBuffers(); hooks.createVertexBuffers(*this);
} }
vk::Pipeline DrawBenchmark::createGraphicsPipeline(vk::RenderPass renderPass) vk::Pipeline DrawTester::createGraphicsPipeline(vk::RenderPass renderPass)
{ {
auto setLayoutBindings = doCreateDescriptorSetLayouts(); auto setLayoutBindings = hooks.createDescriptorSetLayout(*this);
std::vector<vk::DescriptorSetLayout> setLayouts; std::vector<vk::DescriptorSetLayout> setLayouts;
if(!setLayoutBindings.empty()) if(!setLayoutBindings.empty())
...@@ -271,8 +271,8 @@ vk::Pipeline DrawBenchmark::createGraphicsPipeline(vk::RenderPass renderPass) ...@@ -271,8 +271,8 @@ vk::Pipeline DrawBenchmark::createGraphicsPipeline(vk::RenderPass renderPass)
multisampleState.rasterizationSamples = multisample ? vk::SampleCountFlagBits::e4 : vk::SampleCountFlagBits::e1; multisampleState.rasterizationSamples = multisample ? vk::SampleCountFlagBits::e4 : vk::SampleCountFlagBits::e1;
multisampleState.pSampleMask = nullptr; multisampleState.pSampleMask = nullptr;
vk::ShaderModule vertexModule = doCreateVertexShader(); vk::ShaderModule vertexModule = hooks.createVertexShader(*this);
vk::ShaderModule fragmentModule = doCreateFragmentShader(); vk::ShaderModule fragmentModule = hooks.createFragmentShader(*this);
assert(vertexModule); // TODO: if nullptr, use a default assert(vertexModule); // TODO: if nullptr, use a default
assert(fragmentModule); // TODO: if nullptr, use a default assert(fragmentModule); // TODO: if nullptr, use a default
...@@ -307,7 +307,7 @@ vk::Pipeline DrawBenchmark::createGraphicsPipeline(vk::RenderPass renderPass) ...@@ -307,7 +307,7 @@ vk::Pipeline DrawBenchmark::createGraphicsPipeline(vk::RenderPass renderPass)
return pipeline; return pipeline;
} }
void DrawBenchmark::createSynchronizationPrimitives() void DrawTester::createSynchronizationPrimitives()
{ {
vk::SemaphoreCreateInfo semaphoreCreateInfo; vk::SemaphoreCreateInfo semaphoreCreateInfo;
presentCompleteSemaphore = device.createSemaphore(semaphoreCreateInfo); presentCompleteSemaphore = device.createSemaphore(semaphoreCreateInfo);
...@@ -322,7 +322,7 @@ void DrawBenchmark::createSynchronizationPrimitives() ...@@ -322,7 +322,7 @@ void DrawBenchmark::createSynchronizationPrimitives()
} }
} }
void DrawBenchmark::createCommandBuffers(vk::RenderPass renderPass) void DrawTester::createCommandBuffers(vk::RenderPass renderPass)
{ {
vk::CommandPoolCreateInfo commandPoolCreateInfo; vk::CommandPoolCreateInfo commandPoolCreateInfo;
commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex; commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex;
...@@ -351,7 +351,7 @@ void DrawBenchmark::createCommandBuffers(vk::RenderPass renderPass) ...@@ -351,7 +351,7 @@ void DrawBenchmark::createCommandBuffers(vk::RenderPass renderPass)
descriptorSets = device.allocateDescriptorSets(allocInfo); descriptorSets = device.allocateDescriptorSets(allocInfo);
doUpdateDescriptorSet(commandPool, descriptorSets[0]); hooks.updateDescriptorSet(*this, commandPool, descriptorSets[0]);
} }
vk::CommandBufferAllocateInfo commandBufferAllocateInfo; vk::CommandBufferAllocateInfo commandBufferAllocateInfo;
...@@ -402,7 +402,7 @@ void DrawBenchmark::createCommandBuffers(vk::RenderPass renderPass) ...@@ -402,7 +402,7 @@ void DrawBenchmark::createCommandBuffers(vk::RenderPass renderPass)
} }
} }
void DrawBenchmark::addVertexBuffer(void *vertexBufferData, size_t vertexBufferDataSize, size_t vertexSize, std::vector<vk::VertexInputAttributeDescription> inputAttributes) void DrawTester::addVertexBuffer(void *vertexBufferData, size_t vertexBufferDataSize, size_t vertexSize, std::vector<vk::VertexInputAttributeDescription> inputAttributes)
{ {
assert(!vertices.buffer); // For now, only support adding once assert(!vertices.buffer); // For now, only support adding once
...@@ -437,7 +437,7 @@ void DrawBenchmark::addVertexBuffer(void *vertexBufferData, size_t vertexBufferD ...@@ -437,7 +437,7 @@ void DrawBenchmark::addVertexBuffer(void *vertexBufferData, size_t vertexBufferD
vertices.numVertices = static_cast<uint32_t>(vertexBufferDataSize / vertexSize); vertices.numVertices = static_cast<uint32_t>(vertexBufferDataSize / vertexSize);
} }
vk::ShaderModule DrawBenchmark::createShaderModule(const char *glslSource, EShLanguage glslLanguage) vk::ShaderModule DrawTester::createShaderModule(const char *glslSource, EShLanguage glslLanguage)
{ {
auto spirv = Util::compileGLSLtoSPIRV(glslSource, glslLanguage); auto spirv = Util::compileGLSLtoSPIRV(glslSource, glslLanguage);
......
...@@ -12,14 +12,14 @@ ...@@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifndef DRAW_BENCHMARK_HPP_ #ifndef DRAW_TESTER_HPP_
#define DRAW_BENCHMARK_HPP_ #define DRAW_TESTER_HPP_
#include "Framebuffer.hpp" #include "Framebuffer.hpp"
#include "Image.hpp" #include "Image.hpp"
#include "Swapchain.hpp" #include "Swapchain.hpp"
#include "Util.hpp" #include "Util.hpp"
#include "VulkanBenchmark.hpp" #include "VulkanTester.hpp"
#include "Window.hpp" #include "Window.hpp"
enum class Multisample enum class Multisample
...@@ -28,62 +28,43 @@ enum class Multisample ...@@ -28,62 +28,43 @@ enum class Multisample
True True
}; };
class DrawBenchmark : public VulkanBenchmark class DrawTester : public VulkanTester
{ {
public: public:
DrawBenchmark(Multisample multisample); using ThisType = DrawTester;
~DrawBenchmark();
DrawTester(Multisample multisample = Multisample::False);
~DrawTester();
void initialize(); void initialize();
void renderFrame(); void renderFrame();
void show(); void show();
private:
void createSynchronizationPrimitives();
void createCommandBuffers(vk::RenderPass renderPass);
void prepareVertices();
void createFramebuffers(vk::RenderPass renderPass);
vk::RenderPass createRenderPass(vk::Format colorFormat);
vk::Pipeline createGraphicsPipeline(vk::RenderPass renderPass);
void addVertexBuffer(void *vertexBufferData, size_t vertexBufferDataSize, size_t vertexSize, std::vector<vk::VertexInputAttributeDescription> inputAttributes);
protected:
///////////////////////// /////////////////////////
// Hooks // Hooks
///////////////////////// /////////////////////////
// Called from prepareVertices. // Called from prepareVertices.
// Child type may call addVertexBuffer() from this function. // Callback may call tester.addVertexBuffer() from this function.
virtual void doCreateVertexBuffers() {} void onCreateVertexBuffers(std::function<void(ThisType &tester)> callback);
// Called from createGraphicsPipeline. // Called from createGraphicsPipeline.
// Child type may return vector of DescriptorSetLayoutBindings for which a DescriptorSetLayout // Callback must return vector of DescriptorSetLayoutBindings for which a DescriptorSetLayout
// will be created and stored in this->descriptorSetLayout. // will be created and stored in this->descriptorSetLayout.
virtual std::vector<vk::DescriptorSetLayoutBinding> doCreateDescriptorSetLayouts() void onCreateDescriptorSetLayouts(std::function<std::vector<vk::DescriptorSetLayoutBinding>(ThisType &tester)> callback);
{
return {};
}
// Called from createGraphicsPipeline. // Called from createGraphicsPipeline.
// Child type may call createShaderModule() and return the result. // Callback should call tester.createShaderModule() and return the result.
virtual vk::ShaderModule doCreateVertexShader() void onCreateVertexShader(std::function<vk::ShaderModule(ThisType &tester)> callback);
{
return nullptr;
}
// Called from createGraphicsPipeline. // Called from createGraphicsPipeline.
// Child type may call createShaderModule() and return the result. // Callback should call tester.createShaderModule() and return the result.
virtual vk::ShaderModule doCreateFragmentShader() void onCreateFragmentShader(std::function<vk::ShaderModule(ThisType &tester)> callback);
{
return nullptr;
}
// Called from createCommandBuffers. // Called from createCommandBuffers.
// Child type may create resources (addImage, addSampler, etc.), and make sure to // Callback may create resources (tester.addImage, tester.addSampler, etc.), and make sure to
// call device.updateDescriptorSets. // call tester.device().updateDescriptorSets.
virtual void doUpdateDescriptorSet(vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet) void onUpdateDescriptorSet(std::function<void(ThisType &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet)> callback);
{
}
///////////////////////// /////////////////////////
// Resource Management // Resource Management
...@@ -122,7 +103,7 @@ protected: ...@@ -122,7 +103,7 @@ protected:
{ {
auto sampler = device.createSampler(samplerCreateInfo); auto sampler = device.createSampler(samplerCreateInfo);
samplers.push_back(sampler); samplers.push_back(sampler);
return { samplers.size() - 1, sampler }; return { samplers.size() - 1, samplers.back() };
} }
vk::Sampler &getSamplerById(size_t id) vk::Sampler &getSamplerById(size_t id)
...@@ -131,6 +112,23 @@ protected: ...@@ -131,6 +112,23 @@ protected:
} }
private: private:
void createSynchronizationPrimitives();
void createCommandBuffers(vk::RenderPass renderPass);
void prepareVertices();
void createFramebuffers(vk::RenderPass renderPass);
vk::RenderPass createRenderPass(vk::Format colorFormat);
vk::Pipeline createGraphicsPipeline(vk::RenderPass renderPass);
void addVertexBuffer(void *vertexBufferData, size_t vertexBufferDataSize, size_t vertexSize, std::vector<vk::VertexInputAttributeDescription> inputAttributes);
struct Hook
{
std::function<void(ThisType &tester)> createVertexBuffers = [](auto &) {};
std::function<std::vector<vk::DescriptorSetLayoutBinding>(ThisType &tester)> createDescriptorSetLayout = [](auto &) { return std::vector<vk::DescriptorSetLayoutBinding>{}; };
std::function<vk::ShaderModule(ThisType &tester)> createVertexShader = [](auto &) { return vk::ShaderModule{}; };
std::function<vk::ShaderModule(ThisType &tester)> createFragmentShader = [](auto &) { return vk::ShaderModule{}; };
std::function<void(ThisType &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet)> updateDescriptorSet = [](auto &, auto &, auto &) {};
} hooks;
const vk::Extent2D windowSize = { 1280, 720 }; const vk::Extent2D windowSize = { 1280, 720 };
const bool multisample; const bool multisample;
...@@ -171,4 +169,29 @@ private: ...@@ -171,4 +169,29 @@ private:
std::vector<vk::CommandBuffer> commandBuffers; // Owning handles std::vector<vk::CommandBuffer> commandBuffers; // Owning handles
}; };
#endif // DRAW_BENCHMARK_HPP_ inline void DrawTester::onCreateVertexBuffers(std::function<void(ThisType &tester)> callback)
{
hooks.createVertexBuffers = std::move(callback);
}
inline void DrawTester::onCreateDescriptorSetLayouts(std::function<std::vector<vk::DescriptorSetLayoutBinding>(ThisType &tester)> callback)
{
hooks.createDescriptorSetLayout = std::move(callback);
}
inline void DrawTester::onCreateVertexShader(std::function<vk::ShaderModule(ThisType &tester)> callback)
{
hooks.createVertexShader = std::move(callback);
}
inline void DrawTester::onCreateFragmentShader(std::function<vk::ShaderModule(ThisType &tester)> callback)
{
hooks.createFragmentShader = std::move(callback);
}
inline void DrawTester::onUpdateDescriptorSet(std::function<void(ThisType &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet)> callback)
{
hooks.updateDescriptorSet = std::move(callback);
}
#endif // DRAW_TESTER_HPP_
...@@ -70,7 +70,7 @@ Swapchain::~Swapchain() ...@@ -70,7 +70,7 @@ Swapchain::~Swapchain()
device.destroySwapchainKHR(swapchain, nullptr); device.destroySwapchainKHR(swapchain, nullptr);
} }
void Swapchain::acquireNextImage(VkSemaphore presentCompleteSemaphore, uint32_t &imageIndex) void Swapchain::acquireNextImage(vk::Semaphore presentCompleteSemaphore, uint32_t &imageIndex)
{ {
auto result = device.acquireNextImageKHR(swapchain, UINT64_MAX, presentCompleteSemaphore, vk::Fence()); auto result = device.acquireNextImageKHR(swapchain, UINT64_MAX, presentCompleteSemaphore, vk::Fence());
imageIndex = result.value; imageIndex = result.value;
......
...@@ -26,7 +26,7 @@ public: ...@@ -26,7 +26,7 @@ public:
Swapchain(vk::PhysicalDevice physicalDevice, vk::Device device, Window &window); Swapchain(vk::PhysicalDevice physicalDevice, vk::Device device, Window &window);
~Swapchain(); ~Swapchain();
void acquireNextImage(VkSemaphore presentCompleteSemaphore, uint32_t &imageIndex); void acquireNextImage(vk::Semaphore presentCompleteSemaphore, uint32_t &imageIndex);
void queuePresent(vk::Queue queue, uint32_t imageIndex, vk::Semaphore waitSemaphore); void queuePresent(vk::Queue queue, uint32_t imageIndex, vk::Semaphore waitSemaphore);
size_t imageCount() const size_t imageCount() const
......
...@@ -157,7 +157,7 @@ std::vector<uint32_t> compileGLSLtoSPIRV(const char *glslSource, EShLanguage gls ...@@ -157,7 +157,7 @@ std::vector<uint32_t> compileGLSLtoSPIRV(const char *glslSource, EShLanguage gls
{ {
std::string debugLog = glslangShader->getInfoDebugLog(); std::string debugLog = glslangShader->getInfoDebugLog();
std::string infoLog = glslangShader->getInfoLog(); std::string infoLog = glslangShader->getInfoLog();
assert(false); assert(false && "Failed to parse shader");
} }
glslang::TIntermediate *intermediateRepresentation = glslangShader->getIntermediate(); glslang::TIntermediate *intermediateRepresentation = glslangShader->getIntermediate();
......
// 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 "VulkanTester.hpp"
#include <fstream>
#if defined(_WIN32)
# define OS_WINDOWS 1
#elif defined(__APPLE__)
# define OS_MAC 1
#elif defined(__ANDROID__)
# define OS_ANDROID 1
#elif defined(__linux__)
# define OS_LINUX 1
#elif defined(__Fuchsia__)
# define OS_FUCHSIA 1
#else
# error Unimplemented platform
#endif
namespace {
std::vector<const char *> getDriverPaths()
{
#if OS_WINDOWS
# if !defined(STANDALONE)
// The DLL is delay loaded (see BUILD.gn), so we can load
// the correct ones from Chrome's swiftshader subdirectory.
// HMODULE libvulkan = LoadLibraryA("swiftshader\\libvulkan.dll");
// EXPECT_NE((HMODULE)NULL, libvulkan);
// return true;
# error TODO: !STANDALONE
# elif defined(NDEBUG)
# if defined(_WIN64)
return { "./build/Release_x64/vk_swiftshader.dll",
"./build/Release/vk_swiftshader.dll",
"./vk_swiftshader.dll" };
# else
return { "./build/Release_Win32/vk_swiftshader.dll",
"./build/Release/vk_swiftshader.dll",
"./vk_swiftshader.dll" };
# endif
# else
# if defined(_WIN64)
return { "./build/Debug_x64/vk_swiftshader.dll",
"./build/Debug/vk_swiftshader.dll",
"./vk_swiftshader.dll" };
# else
return { "./build/Debug_Win32/vk_swiftshader.dll",
"./build/Debug/vk_swiftshader.dll",
"./vk_swiftshader.dll" };
# endif
# endif
#elif OS_MAC
return { "./build/Darwin/libvk_swiftshader.dylib",
"swiftshader/libvk_swiftshader.dylib",
"libvk_swiftshader.dylib" };
#elif OS_LINUX
return { "./build/Linux/libvk_swiftshader.so",
"swiftshader/libvk_swiftshader.so",
"./libvk_swiftshader.so",
"libvk_swiftshader.so" };
#elif OS_ANDROID || OS_FUCHSIA
return
{
"libvk_swiftshader.so"
}
#else
# error Unimplemented platform
return {};
#endif
}
bool fileExists(const char *path)
{
std::ifstream f(path);
return f.good();
}
std::unique_ptr<vk::DynamicLoader> loadDriver()
{
for(auto &p : getDriverPaths())
{
if(!fileExists(p))
continue;
return std::make_unique<vk::DynamicLoader>(p);
}
return {};
}
} // namespace
VulkanTester::~VulkanTester()
{
device.waitIdle();
device.destroy(nullptr);
instance.destroy(nullptr);
}
void VulkanTester::initialize()
{
dl = loadDriver();
assert(dl && dl->success());
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl->getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
instance = vk::createInstance({}, nullptr);
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance);
std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
assert(!physicalDevices.empty());
physicalDevice = physicalDevices[0];
const float defaultQueuePriority = 0.0f;
vk::DeviceQueueCreateInfo queueCreateInfo;
queueCreateInfo.queueFamilyIndex = queueFamilyIndex;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &defaultQueuePriority;
vk::DeviceCreateInfo deviceCreateInfo;
deviceCreateInfo.queueCreateInfoCount = 1;
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
device = physicalDevice.createDevice(deviceCreateInfo, nullptr);
queue = device.getQueue(queueFamilyIndex, 0);
}
...@@ -12,20 +12,25 @@ ...@@ -12,20 +12,25 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifndef VULKAN_BENCHMARK_HPP_ #ifndef VULKAN_TESTER_HPP_
#define VULKAN_BENCHMARK_HPP_ #define VULKAN_TESTER_HPP_
#include "VulkanHeaders.hpp" #include "VulkanHeaders.hpp"
class VulkanBenchmark class VulkanTester
{ {
public: public:
VulkanBenchmark() = default; VulkanTester() = default;
virtual ~VulkanBenchmark(); virtual ~VulkanTester();
// Call once after construction so that virtual functions may be called during init // Call once after construction so that virtual functions may be called during init
void initialize(); void initialize();
const vk::DynamicLoader &dynamicLoader() const { return *dl; }
vk::Device &getDevice() { return this->device; }
vk::Queue &getQueue() { return this->queue; }
uint32_t getQueueFamilyIndex() const { return queueFamilyIndex; }
private: private:
std::unique_ptr<vk::DynamicLoader> dl; std::unique_ptr<vk::DynamicLoader> dl;
...@@ -38,4 +43,4 @@ protected: ...@@ -38,4 +43,4 @@ protected:
vk::Queue queue; vk::Queue queue;
}; };
#endif // VULKAN_BENCHMARK_HPP_ #endif // VULKAN_TESTER_HPP_
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