VulkanBenchmarks: add validation layers and load via ICD

In DEBUG builds, enable validation layers: VK_LAYER_KHRONOS_validation and VK_LAYER_LUNARG_standard_validation. Also register the debug utils messenger ext callback for when validation layers report a problem. We can force validation layers in non-DEBUG by defining ENABLE_VALIDATION_LAYERS to 1. In order to be able to use validation layers, load the Vulkan driver via ICD, rather than directly. To load SwiftShader, generate a temp icd.json file pointing at the driver path, and temporarily set the VK_ICD_FILENAMES env var to point at it when we load the ICD. This also allows us to load the native GPU driver by defining LOAD_NATIVE_DRIVER to 1 (default is 0). Fixed errors reported by enabling validation layers: * TriangleSampleTexture had a mismatched binding number for the sampler2D * Correctly set memoryTypeIndex for allocations instead of 0 Bug: b/176981107 Change-Id: I3c791086acea048b73d3568d6d7a45d8e0100c17 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/52749 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 aa46953c
...@@ -12,11 +12,11 @@ ...@@ -12,11 +12,11 @@
// 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 "Util.hpp"
#include "VulkanTester.hpp" #include "VulkanTester.hpp"
#include "benchmark/benchmark.h" #include "benchmark/benchmark.h"
#include <cassert> #include <cassert>
class ClearImageBenchmark class ClearImageBenchmark
{ {
public: public:
...@@ -24,6 +24,7 @@ public: ...@@ -24,6 +24,7 @@ public:
{ {
tester.initialize(); tester.initialize();
auto &device = tester.getDevice(); auto &device = tester.getDevice();
auto &physicalDevice = tester.getPhysicalDevice();
vk::ImageCreateInfo imageInfo; vk::ImageCreateInfo imageInfo;
imageInfo.imageType = vk::ImageType::e2D; imageInfo.imageType = vk::ImageType::e2D;
...@@ -42,7 +43,7 @@ public: ...@@ -42,7 +43,7 @@ public:
vk::MemoryAllocateInfo allocateInfo; vk::MemoryAllocateInfo allocateInfo;
allocateInfo.allocationSize = memoryRequirements.size; allocateInfo.allocationSize = memoryRequirements.size;
allocateInfo.memoryTypeIndex = 0; allocateInfo.memoryTypeIndex = Util::getMemoryTypeIndex(physicalDevice, memoryRequirements.memoryTypeBits);
memory = device.allocateMemory(allocateInfo); memory = device.allocateMemory(allocateInfo);
......
...@@ -198,7 +198,7 @@ static void TriangleSampleTexture(benchmark::State &state, Multisample multisamp ...@@ -198,7 +198,7 @@ static void TriangleSampleTexture(benchmark::State &state, Multisample multisamp
layout(location = 0) out vec4 outColor; layout(location = 0) out vec4 outColor;
layout(binding = 0) uniform sampler2D texSampler; layout(binding = 1) uniform sampler2D texSampler;
void main() void main()
{ {
...@@ -221,9 +221,10 @@ static void TriangleSampleTexture(benchmark::State &state, Multisample multisamp ...@@ -221,9 +221,10 @@ static void TriangleSampleTexture(benchmark::State &state, Multisample multisamp
tester.onUpdateDescriptorSet([](DrawTester &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet) { tester.onUpdateDescriptorSet([](DrawTester &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet) {
auto &device = tester.getDevice(); auto &device = tester.getDevice();
auto &physicalDevice = tester.getPhysicalDevice();
auto &queue = tester.getQueue(); auto &queue = tester.getQueue();
auto &texture = tester.addImage(device, 16, 16, vk::Format::eR8G8B8A8Unorm).obj; auto &texture = tester.addImage(device, physicalDevice, 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;
......
...@@ -193,7 +193,7 @@ void DrawTester::createFramebuffers(vk::RenderPass renderPass) ...@@ -193,7 +193,7 @@ void DrawTester::createFramebuffers(vk::RenderPass renderPass)
for(size_t i = 0; i < framebuffers.size(); i++) for(size_t i = 0; i < framebuffers.size(); i++)
{ {
framebuffers[i].reset(new Framebuffer(device, swapchain->getImageView(i), swapchain->colorFormat, renderPass, swapchain->getExtent(), multisample)); framebuffers[i].reset(new Framebuffer(device, physicalDevice, swapchain->getImageView(i), swapchain->colorFormat, renderPass, swapchain->getExtent(), multisample));
} }
} }
...@@ -392,10 +392,13 @@ void DrawTester::createCommandBuffers(vk::RenderPass renderPass) ...@@ -392,10 +392,13 @@ void DrawTester::createCommandBuffers(vk::RenderPass renderPass)
} }
// Draw // Draw
commandBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline); if(vertices.numVertices > 0)
VULKAN_HPP_NAMESPACE::DeviceSize offset = 0; {
commandBuffers[i].bindVertexBuffers(0, 1, &vertices.buffer, &offset); commandBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
commandBuffers[i].draw(vertices.numVertices, 1, 0, 0); VULKAN_HPP_NAMESPACE::DeviceSize offset = 0;
commandBuffers[i].bindVertexBuffers(0, 1, &vertices.buffer, &offset);
commandBuffers[i].draw(vertices.numVertices, 1, 0, 0);
}
commandBuffers[i].endRenderPass(); commandBuffers[i].endRenderPass();
commandBuffers[i].end(); commandBuffers[i].end();
......
...@@ -148,7 +148,7 @@ private: ...@@ -148,7 +148,7 @@ private:
std::vector<vk::VertexInputAttributeDescription> inputAttributes; std::vector<vk::VertexInputAttributeDescription> inputAttributes;
vk::PipelineVertexInputStateCreateInfo inputState; vk::PipelineVertexInputStateCreateInfo inputState;
uint32_t numVertices; uint32_t numVertices = 0;
} vertices; } vertices;
vk::DescriptorSetLayout descriptorSetLayout; // Owning handle vk::DescriptorSetLayout descriptorSetLayout; // Owning handle
......
...@@ -14,14 +14,14 @@ ...@@ -14,14 +14,14 @@
#include "Framebuffer.hpp" #include "Framebuffer.hpp"
Framebuffer::Framebuffer(vk::Device device, vk::ImageView attachment, vk::Format colorFormat, vk::RenderPass renderPass, vk::Extent2D extent, bool multisample) Framebuffer::Framebuffer(vk::Device device, vk::PhysicalDevice physicalDevice, vk::ImageView attachment, vk::Format colorFormat, vk::RenderPass renderPass, vk::Extent2D extent, bool multisample)
: device(device) : device(device)
{ {
std::vector<vk::ImageView> attachments(multisample ? 2 : 1); std::vector<vk::ImageView> attachments(multisample ? 2 : 1);
if(multisample) if(multisample)
{ {
multisampleImage.reset(new Image(device, extent.width, extent.height, colorFormat, vk::SampleCountFlagBits::e4)); multisampleImage.reset(new Image(device, physicalDevice, extent.width, extent.height, colorFormat, vk::SampleCountFlagBits::e4));
// We'll be rendering to attachment location 0 // We'll be rendering to attachment location 0
attachments[0] = multisampleImage->getImageView(); attachments[0] = multisampleImage->getImageView();
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
class Framebuffer class Framebuffer
{ {
public: public:
Framebuffer(vk::Device device, vk::ImageView attachment, vk::Format colorFormat, vk::RenderPass renderPass, vk::Extent2D extent, bool multisample); Framebuffer(vk::Device device, vk::PhysicalDevice physicalDevice, vk::ImageView attachment, vk::Format colorFormat, vk::RenderPass renderPass, vk::Extent2D extent, bool multisample);
~Framebuffer(); ~Framebuffer();
vk::Framebuffer getFramebuffer() vk::Framebuffer getFramebuffer()
......
...@@ -13,8 +13,9 @@ ...@@ -13,8 +13,9 @@
// limitations under the License. // limitations under the License.
#include "Image.hpp" #include "Image.hpp"
#include "Util.hpp"
Image::Image(vk::Device device, uint32_t width, uint32_t height, vk::Format format, vk::SampleCountFlagBits sampleCount /*= vk::SampleCountFlagBits::e1*/) Image::Image(vk::Device device, vk::PhysicalDevice physicalDevice, uint32_t width, uint32_t height, vk::Format format, vk::SampleCountFlagBits sampleCount /*= vk::SampleCountFlagBits::e1*/)
: device(device) : device(device)
{ {
vk::ImageCreateInfo imageInfo; vk::ImageCreateInfo imageInfo;
...@@ -34,7 +35,7 @@ Image::Image(vk::Device device, uint32_t width, uint32_t height, vk::Format form ...@@ -34,7 +35,7 @@ Image::Image(vk::Device device, uint32_t width, uint32_t height, vk::Format form
vk::MemoryAllocateInfo allocateInfo; vk::MemoryAllocateInfo allocateInfo;
allocateInfo.allocationSize = memoryRequirements.size; allocateInfo.allocationSize = memoryRequirements.size;
allocateInfo.memoryTypeIndex = 0; //getMemoryTypeIndex(memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eDeviceLocal); allocateInfo.memoryTypeIndex = Util::getMemoryTypeIndex(physicalDevice, memoryRequirements.memoryTypeBits);
imageMemory = device.allocateMemory(allocateInfo); imageMemory = device.allocateMemory(allocateInfo);
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
class Image class Image
{ {
public: public:
Image(vk::Device device, uint32_t width, uint32_t height, vk::Format format, vk::SampleCountFlagBits sampleCount = vk::SampleCountFlagBits::e1); Image(vk::Device device, vk::PhysicalDevice physicalDevice, uint32_t width, uint32_t height, vk::Format format, vk::SampleCountFlagBits sampleCount = vk::SampleCountFlagBits::e1);
~Image(); ~Image();
vk::Image getImage() vk::Image getImage()
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
namespace Util { namespace Util {
uint32_t getMemoryTypeIndex(vk::PhysicalDevice physicalDevice, uint32_t typeBits, vk::MemoryPropertyFlags properties); uint32_t getMemoryTypeIndex(vk::PhysicalDevice physicalDevice, uint32_t typeBits, vk::MemoryPropertyFlags properties = {});
vk::CommandBuffer beginSingleTimeCommands(vk::Device device, vk::CommandPool commandPool); vk::CommandBuffer beginSingleTimeCommands(vk::Device device, vk::CommandPool commandPool);
......
...@@ -13,7 +13,30 @@ ...@@ -13,7 +13,30 @@
// limitations under the License. // limitations under the License.
#include "VulkanTester.hpp" #include "VulkanTester.hpp"
#include <cstdlib>
#include <filesystem>
#include <fstream> #include <fstream>
#include <iostream>
namespace fs = std::filesystem;
// By default, load SwiftShader via loader
#ifndef LOAD_NATIVE_DRIVER
# define LOAD_NATIVE_DRIVER 0
#endif
#ifndef LOAD_SWIFTSHADER_DIRECTLY
# define LOAD_SWIFTSHADER_DIRECTLY 0
#endif
#if LOAD_NATIVE_DRIVER && LOAD_SWIFTSHADER_DIRECTLY
# error Enable only one of LOAD_NATIVE_DRIVER and LOAD_SWIFTSHADER_DIRECTLY
#endif
// By default, enable validation layers in DEBUG builds
#if !defined(ENABLE_VALIDATION_LAYERS) && !defined(NDEBUG)
# define ENABLE_VALIDATION_LAYERS 1
#endif
#if defined(_WIN32) #if defined(_WIN32)
# define OS_WINDOWS 1 # define OS_WINDOWS 1
...@@ -33,7 +56,107 @@ ...@@ -33,7 +56,107 @@
# error Unimplemented platform # error Unimplemented platform
#endif #endif
// TODO: move to its own header/cpp
// Wraps a single environment variable, allowing it to be set
// and automatically restored on destruction.
class ScopedSetEnvVar
{
public:
ScopedSetEnvVar(std::string name)
: name(name)
{
assert(!name.empty());
}
ScopedSetEnvVar(std::string name, std::string value)
: name(name)
{
set(value);
}
~ScopedSetEnvVar()
{
restore();
}
void set(std::string value)
{
restore();
if(auto ov = getEnv(name.data()))
{
oldValue = ov;
}
putEnv((name + std::string("=") + value).c_str());
}
void restore()
{
if(!oldValue.empty())
{
putEnv((name + std::string("=") + oldValue).c_str());
oldValue.clear();
}
}
private:
void putEnv(const char *env)
{
// POSIX putenv needs 'env' to live beyond the call
envCopy = env;
#if OS_WINDOWS
[[maybe_unused]] auto r = ::_putenv(envCopy.c_str());
assert(r == 0);
#else
[[maybe_unused]] auto r = ::putenv(const_cast<char *>(envCopy.c_str()));
assert(r == 0);
#endif
}
const char *getEnv(const char *name)
{
return ::getenv(name);
}
std::string name;
std::string oldValue;
std::string envCopy;
};
// Generates a temporary icd.json file that sets library_path at the input driverPath,
// and sets VK_ICD_FILENAMES environment variable to this file, restoring the env var
// and deleting the temp file on destruction.
class ScopedSetIcdFilenames
{
public:
ScopedSetIcdFilenames() = default;
ScopedSetIcdFilenames(const char *driverPath)
{
std::ofstream fout(icdFileName);
assert(fout && "Failed to create generated icd file");
fout << R"raw({ "file_format_version": "1.0.0", "ICD": { "library_path": ")raw" << driverPath << R"raw(", "api_version": "1.0.5" } } )raw";
fout.close();
setEnvVar.set(icdFileName);
}
~ScopedSetIcdFilenames()
{
//TODO(b/180494886): fix C++17 filesystem issues on macOS
#if !OS_MAC
if(fs::exists("vk_swiftshader_generated_icd.json"))
{
fs::remove("vk_swiftshader_generated_icd.json");
}
#endif
}
private:
static constexpr const char *icdFileName = "vk_swiftshader_generated_icd.json";
ScopedSetEnvVar setEnvVar{ "VK_ICD_FILENAMES" };
};
namespace { namespace {
std::vector<const char *> getDriverPaths() std::vector<const char *> getDriverPaths()
{ {
#if OS_WINDOWS #if OS_WINDOWS
...@@ -91,24 +214,25 @@ bool fileExists(const char *path) ...@@ -91,24 +214,25 @@ bool fileExists(const char *path)
return f.good(); return f.good();
} }
std::unique_ptr<vk::DynamicLoader> loadDriver() std::string findDriverPath()
{ {
for(auto &p : getDriverPaths()) for(auto &path : getDriverPaths())
{ {
if(!fileExists(p)) if(fileExists(path))
continue; return path;
return std::make_unique<vk::DynamicLoader>(p);
} }
#if(OS_MAC || OS_LINUX || OS_ANDROID || OS_FUCHSIA) #if(OS_LINUX || OS_ANDROID || OS_FUCHSIA)
// On Linux-based OSes, the lib path may be resolved by dlopen // On Linux-based OSes, the lib path may be resolved by dlopen
for(auto &p : getDriverPaths()) for(auto &path : getDriverPaths())
{ {
auto lib = dlopen(p, RTLD_LAZY | RTLD_LOCAL); auto lib = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
if(lib) if(lib)
{ {
char libPath[2048] = { '\0' };
dlinfo(lib, RTLD_DI_ORIGIN, libPath);
dlclose(lib); dlclose(lib);
return std::make_unique<vk::DynamicLoader>(p); return std::string{ libPath } + "/" + path;
} }
} }
#endif #endif
...@@ -118,10 +242,13 @@ std::unique_ptr<vk::DynamicLoader> loadDriver() ...@@ -118,10 +242,13 @@ std::unique_ptr<vk::DynamicLoader> loadDriver()
} // namespace } // namespace
VulkanTester::VulkanTester() = default;
VulkanTester::~VulkanTester() VulkanTester::~VulkanTester()
{ {
device.waitIdle(); device.waitIdle();
device.destroy(nullptr); device.destroy(nullptr);
if(debugReport) instance.destroy(debugReport);
instance.destroy(nullptr); instance.destroy(nullptr);
} }
...@@ -133,9 +260,75 @@ void VulkanTester::initialize() ...@@ -133,9 +260,75 @@ void VulkanTester::initialize()
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl->getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr"); PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl->getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
instance = vk::createInstance({}, nullptr); vk::InstanceCreateInfo instanceCreateInfo;
std::vector<const char *> extensionNames
{
VK_KHR_SURFACE_EXTENSION_NAME,
#if defined(USE_HEADLESS_SURFACE)
VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME,
#endif
#if defined(VK_USE_PLATFORM_WIN32_KHR)
VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
#endif
};
#if ENABLE_VALIDATION_LAYERS
extensionNames.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
#endif
auto addLayerIfAvailable = [](std::vector<const char *> &layers, const char *layer) {
static auto layerProperties = vk::enumerateInstanceLayerProperties();
if(std::find_if(layerProperties.begin(), layerProperties.end(), [layer](auto &lp) {
return strcmp(layer, lp.layerName) == 0;
}) != layerProperties.end())
{
//std::cout << "Enabled layer: " << layer << std::endl;
layers.push_back(layer);
}
};
std::vector<const char *> layerNames;
#if ENABLE_VALIDATION_LAYERS
addLayerIfAvailable(layerNames, "VK_LAYER_KHRONOS_validation");
addLayerIfAvailable(layerNames, "VK_LAYER_LUNARG_standard_validation");
#endif
instanceCreateInfo.ppEnabledExtensionNames = extensionNames.data();
instanceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(extensionNames.size());
instanceCreateInfo.ppEnabledLayerNames = layerNames.data();
instanceCreateInfo.enabledLayerCount = static_cast<uint32_t>(layerNames.size());
instance = vk::createInstance(instanceCreateInfo, nullptr);
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance); VULKAN_HPP_DEFAULT_DISPATCHER.init(instance);
#if ENABLE_VALIDATION_LAYERS
if(VULKAN_HPP_DEFAULT_DISPATCHER.vkCreateDebugUtilsMessengerEXT)
{
vk::DebugUtilsMessengerCreateInfoEXT debugInfo;
debugInfo.messageSeverity =
// vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning;
debugInfo.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance;
PFN_vkDebugUtilsMessengerCallbackEXT debugInfoCallback =
[](
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageTypes,
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
void *pUserData) -> VkBool32 {
//assert(false);
std::cerr << "[DebugInfoCallback] " << pCallbackData->pMessage << std::endl;
return VK_FALSE;
};
debugInfo.pfnUserCallback = debugInfoCallback;
debugReport = instance.createDebugUtilsMessengerEXT(debugInfo);
}
#endif
std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices(); std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
assert(!physicalDevices.empty()); assert(!physicalDevices.empty());
physicalDevice = physicalDevices[0]; physicalDevice = physicalDevices[0];
...@@ -146,11 +339,56 @@ void VulkanTester::initialize() ...@@ -146,11 +339,56 @@ void VulkanTester::initialize()
queueCreateInfo.queueCount = 1; queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &defaultQueuePriority; queueCreateInfo.pQueuePriorities = &defaultQueuePriority;
std::vector<const char *> deviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
vk::DeviceCreateInfo deviceCreateInfo; vk::DeviceCreateInfo deviceCreateInfo;
deviceCreateInfo.queueCreateInfoCount = 1; deviceCreateInfo.queueCreateInfoCount = 1;
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
device = physicalDevice.createDevice(deviceCreateInfo, nullptr); device = physicalDevice.createDevice(deviceCreateInfo, nullptr);
queue = device.getQueue(queueFamilyIndex, 0); queue = device.getQueue(queueFamilyIndex, 0);
} }
std::unique_ptr<vk::DynamicLoader> VulkanTester::loadDriver()
{
if(LOAD_NATIVE_DRIVER)
{
return std::make_unique<vk::DynamicLoader>();
}
auto driverPath = findDriverPath();
assert(!driverPath.empty());
if(LOAD_SWIFTSHADER_DIRECTLY)
{
return std::make_unique<vk::DynamicLoader>(driverPath);
}
// Load SwiftShader via loader
// Set VK_ICD_FILENAMES env var so it gets picked up by the loading of the ICD driver
setIcdFilenames = std::make_unique<ScopedSetIcdFilenames>(driverPath.c_str());
std::unique_ptr<vk::DynamicLoader> dl;
#ifndef VULKAN_HPP_NO_EXCEPTIONS
try
{
dl = std::make_unique<vk::DynamicLoader>();
}
catch(std::exception &ex)
{
std::cerr << "vk::DynamicLoader exception: " << ex.what() << std::endl;
std::cerr << "Falling back to loading SwiftShader directly (i.e. no validation layers)" << std::endl;
dl = std::make_unique<vk::DynamicLoader>(driverPath);
}
#else
dl = std::make_unique<vk::DynamicLoader>();
#endif
return dl;
}
...@@ -20,19 +20,24 @@ ...@@ -20,19 +20,24 @@
class VulkanTester class VulkanTester
{ {
public: public:
VulkanTester() = default; VulkanTester();
virtual ~VulkanTester(); 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; } const vk::DynamicLoader &dynamicLoader() const { return *dl; }
vk::Device &getDevice() { return this->device; } vk::PhysicalDevice &getPhysicalDevice() { return physicalDevice; }
vk::Queue &getQueue() { return this->queue; } vk::Device &getDevice() { return device; }
vk::Queue &getQueue() { return queue; }
uint32_t getQueueFamilyIndex() const { return queueFamilyIndex; } uint32_t getQueueFamilyIndex() const { return queueFamilyIndex; }
private: private:
std::unique_ptr<vk::DynamicLoader> loadDriver();
std::unique_ptr<class ScopedSetIcdFilenames> setIcdFilenames;
std::unique_ptr<vk::DynamicLoader> dl; std::unique_ptr<vk::DynamicLoader> dl;
vk::DebugUtilsMessengerEXT debugReport;
protected: protected:
const uint32_t queueFamilyIndex = 0; const uint32_t queueFamilyIndex = 0;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#if USE_HEADLESS_SURFACE #if USE_HEADLESS_SURFACE
Window::Window(vk::Instance instance, vk::Extent2D windowSize) Window::Window(vk::Instance instance, vk::Extent2D windowSize)
: instance(instance)
{ {
vk::HeadlessSurfaceCreateInfoEXT surfaceCreateInfo; vk::HeadlessSurfaceCreateInfoEXT surfaceCreateInfo;
surface = instance.createHeadlessSurfaceEXT(surfaceCreateInfo); surface = instance.createHeadlessSurfaceEXT(surfaceCreateInfo);
...@@ -40,6 +41,7 @@ void Window::show() ...@@ -40,6 +41,7 @@ void Window::show()
#elif defined(_WIN32) #elif defined(_WIN32)
Window::Window(vk::Instance instance, vk::Extent2D windowSize) Window::Window(vk::Instance instance, vk::Extent2D windowSize)
: instance(instance)
{ {
windowClass.cbSize = sizeof(WNDCLASSEX); windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.style = CS_HREDRAW | CS_VREDRAW; windowClass.style = CS_HREDRAW | CS_VREDRAW;
......
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