mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-25 13:21:55 +00:00
Fix vulkan validation errors
This commit is contained in:
parent
ce376eb558
commit
b06f1b6128
4 changed files with 267 additions and 13 deletions
|
@ -14,13 +14,232 @@
|
|||
#include <algorithm>
|
||||
#include <zlib.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <DbgHelp.h>
|
||||
#else
|
||||
#include <execinfo.h>
|
||||
#include <cxxabi.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#endif
|
||||
|
||||
extern int Multisample;
|
||||
extern int LightBounce;
|
||||
extern float GridSize;
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma comment(lib, "dbghelp.lib")
|
||||
class NativeSymbolResolver
|
||||
{
|
||||
public:
|
||||
NativeSymbolResolver() { SymInitialize(GetCurrentProcess(), nullptr, TRUE); }
|
||||
~NativeSymbolResolver() { SymCleanup(GetCurrentProcess()); }
|
||||
|
||||
std::string GetName(void* frame)
|
||||
{
|
||||
std::string s;
|
||||
|
||||
unsigned char buffer[sizeof(IMAGEHLP_SYMBOL64) + 128];
|
||||
IMAGEHLP_SYMBOL64* symbol64 = reinterpret_cast<IMAGEHLP_SYMBOL64*>(buffer);
|
||||
memset(symbol64, 0, sizeof(IMAGEHLP_SYMBOL64) + 128);
|
||||
symbol64->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||
symbol64->MaxNameLength = 128;
|
||||
|
||||
DWORD64 displacement = 0;
|
||||
BOOL result = SymGetSymFromAddr64(GetCurrentProcess(), (DWORD64)frame, &displacement, symbol64);
|
||||
if (result)
|
||||
{
|
||||
IMAGEHLP_LINE64 line64;
|
||||
DWORD displacement = 0;
|
||||
memset(&line64, 0, sizeof(IMAGEHLP_LINE64));
|
||||
line64.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
result = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)frame, &displacement, &line64);
|
||||
if (result)
|
||||
{
|
||||
s = std::string("Called from ") + symbol64->Name + " at " + line64.FileName + ", line " + std::to_string(line64.LineNumber) + "\n", symbol64->Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
s = std::string("Called from ") + symbol64->Name + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
};
|
||||
#else
|
||||
class NativeSymbolResolver
|
||||
{
|
||||
public:
|
||||
std::string GetName(void* frame)
|
||||
{
|
||||
std::string s;
|
||||
char** strings;
|
||||
void* frames[1] = { frame };
|
||||
strings = backtrace_symbols(frames, 1);
|
||||
|
||||
// Decode the strings
|
||||
char* ptr = strings[0];
|
||||
char* filename = ptr;
|
||||
const char* function = "";
|
||||
|
||||
// Find function name
|
||||
while (*ptr)
|
||||
{
|
||||
if (*ptr == '(') // Found function name
|
||||
{
|
||||
*(ptr++) = 0;
|
||||
function = ptr;
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
// Find offset
|
||||
if (function[0]) // Only if function was found
|
||||
{
|
||||
while (*ptr)
|
||||
{
|
||||
if (*ptr == '+') // Found function offset
|
||||
{
|
||||
*(ptr++) = 0;
|
||||
break;
|
||||
}
|
||||
if (*ptr == ')') // Not found function offset, but found, end of function
|
||||
{
|
||||
*(ptr++) = 0;
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
int status;
|
||||
char* new_function = abi::__cxa_demangle(function, nullptr, nullptr, &status);
|
||||
if (new_function) // Was correctly decoded
|
||||
{
|
||||
function = new_function;
|
||||
}
|
||||
|
||||
s = std::string("Called from ") + function + " at " + filename + "\n";
|
||||
|
||||
if (new_function)
|
||||
{
|
||||
free(new_function);
|
||||
}
|
||||
|
||||
free(strings);
|
||||
return s;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
static int CaptureStackTrace(int max_frames, void** out_frames)
|
||||
{
|
||||
memset(out_frames, 0, sizeof(void*) * max_frames);
|
||||
|
||||
#ifdef _WIN64
|
||||
// RtlCaptureStackBackTrace doesn't support RtlAddFunctionTable..
|
||||
|
||||
CONTEXT context;
|
||||
RtlCaptureContext(&context);
|
||||
|
||||
UNWIND_HISTORY_TABLE history;
|
||||
memset(&history, 0, sizeof(UNWIND_HISTORY_TABLE));
|
||||
|
||||
ULONG64 establisherframe = 0;
|
||||
PVOID handlerdata = nullptr;
|
||||
|
||||
int frame;
|
||||
for (frame = 0; frame < max_frames; frame++)
|
||||
{
|
||||
ULONG64 imagebase;
|
||||
PRUNTIME_FUNCTION rtfunc = RtlLookupFunctionEntry(context.Rip, &imagebase, &history);
|
||||
|
||||
KNONVOLATILE_CONTEXT_POINTERS nvcontext;
|
||||
memset(&nvcontext, 0, sizeof(KNONVOLATILE_CONTEXT_POINTERS));
|
||||
if (!rtfunc)
|
||||
{
|
||||
// Leaf function
|
||||
context.Rip = (ULONG64)(*(PULONG64)context.Rsp);
|
||||
context.Rsp += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlVirtualUnwind(UNW_FLAG_NHANDLER, imagebase, context.Rip, rtfunc, &context, &handlerdata, &establisherframe, &nvcontext);
|
||||
}
|
||||
|
||||
if (!context.Rip)
|
||||
break;
|
||||
|
||||
out_frames[frame] = (void*)context.Rip;
|
||||
}
|
||||
return frame;
|
||||
|
||||
#elif defined(WIN32)
|
||||
return 0;//return RtlCaptureStackBackTrace(0, MIN(max_frames, 32), out_frames, nullptr);
|
||||
#else
|
||||
return backtrace(out_frames, max_frames);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string CaptureStackTraceText(int framesToSkip, bool includeNativeFrames)
|
||||
{
|
||||
void* frames[32];
|
||||
int numframes = CaptureStackTrace(32, frames);
|
||||
|
||||
std::unique_ptr<NativeSymbolResolver> nativeSymbols;
|
||||
if (includeNativeFrames)
|
||||
nativeSymbols.reset(new NativeSymbolResolver());
|
||||
|
||||
std::string s;
|
||||
for (int i = framesToSkip + 1; i < numframes; i++)
|
||||
{
|
||||
s += nativeSymbols->GetName(frames[i]);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
GPURaytracer::GPURaytracer()
|
||||
{
|
||||
device = std::make_unique<VulkanDevice>();
|
||||
auto printLog = [](const char* typestr, const std::string& msg)
|
||||
{
|
||||
printf("\n[%s] %s\n", typestr, msg.c_str());
|
||||
|
||||
std::string callstack = CaptureStackTraceText(0, true);
|
||||
if (!callstack.empty())
|
||||
printf("%s\n", callstack.c_str());
|
||||
};
|
||||
device = std::make_unique<VulkanDevice>(0, true, printLog);
|
||||
|
||||
const auto& props = device->physicalDevice.properties;
|
||||
|
||||
std::string deviceType;
|
||||
switch (props.deviceType)
|
||||
{
|
||||
case VK_PHYSICAL_DEVICE_TYPE_OTHER: deviceType = "other"; break;
|
||||
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: deviceType = "integrated gpu"; break;
|
||||
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: deviceType = "discrete gpu"; break;
|
||||
case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: deviceType = "virtual gpu"; break;
|
||||
case VK_PHYSICAL_DEVICE_TYPE_CPU: deviceType = "cpu"; break;
|
||||
default: deviceType = std::to_string(props.deviceType); break;
|
||||
}
|
||||
|
||||
std::string apiVersion = std::to_string(VK_VERSION_MAJOR(props.apiVersion)) + "." + std::to_string(VK_VERSION_MINOR(props.apiVersion)) + "." + std::to_string(VK_VERSION_PATCH(props.apiVersion));
|
||||
std::string driverVersion = std::to_string(VK_VERSION_MAJOR(props.driverVersion)) + "." + std::to_string(VK_VERSION_MINOR(props.driverVersion)) + "." + std::to_string(VK_VERSION_PATCH(props.driverVersion));
|
||||
|
||||
printf("Vulkan device: %s\n", props.deviceName);
|
||||
printf("Vulkan device type: %s\n", deviceType.c_str());
|
||||
printf("Vulkan version: %s (api) %s (driver)\n", apiVersion.c_str(), driverVersion.c_str());
|
||||
/*
|
||||
printf("Vulkan extensions:");
|
||||
for (const VkExtensionProperties& p : device->physicalDevice.extensions)
|
||||
{
|
||||
printf(" %s", p.extensionName);
|
||||
}
|
||||
printf("\n");
|
||||
*/
|
||||
}
|
||||
|
||||
GPURaytracer::~GPURaytracer()
|
||||
|
@ -33,6 +252,7 @@ void GPURaytracer::Raytrace(LevelMesh* level)
|
|||
|
||||
cmdpool = std::make_unique<VulkanCommandPool>(device.get(), device->graphicsFamily);
|
||||
cmdbuffer = cmdpool->createBuffer();
|
||||
cmdbuffer->begin();
|
||||
|
||||
printf("Creating vertex and index buffers\n");
|
||||
CreateVertexAndIndexBuffers();
|
||||
|
@ -43,6 +263,8 @@ void GPURaytracer::Raytrace(LevelMesh* level)
|
|||
printf("Creating top level acceleration structure\n");
|
||||
CreateTopLevelAccelerationStructure();
|
||||
|
||||
cmdbuffer->end();
|
||||
|
||||
printf("Tracing light probes\n");
|
||||
|
||||
Worker::RunJob((int)mesh->lightProbes.size(), [=](int id) {
|
||||
|
@ -280,12 +502,12 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
|
|||
size_t indexoffset = vertexoffset + vertexbuffersize;
|
||||
|
||||
BufferBuilder vbuilder;
|
||||
vbuilder.setUsage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||
vbuilder.setUsage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR);
|
||||
vbuilder.setSize(vertexbuffersize);
|
||||
vertexBuffer = vbuilder.create(device.get());
|
||||
|
||||
BufferBuilder ibuilder;
|
||||
ibuilder.setUsage(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||
ibuilder.setUsage(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR);
|
||||
ibuilder.setSize(indexbuffersize);
|
||||
indexBuffer = ibuilder.create(device.get());
|
||||
|
||||
|
@ -298,8 +520,8 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
|
|||
memcpy(data + indexoffset, mesh->MeshElements.Data(), indexbuffersize);
|
||||
transferBuffer->Unmap();
|
||||
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), vertexBuffer.get(), vertexoffset);
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), indexBuffer.get(), indexoffset);
|
||||
//cmdbuffer->copyBuffer(transferBuffer.get(), vertexBuffer.get(), vertexoffset);
|
||||
//cmdbuffer->copyBuffer(transferBuffer.get(), indexBuffer.get(), indexoffset);
|
||||
|
||||
VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER };
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
|
@ -438,9 +660,15 @@ void GPURaytracer::CreateTopLevelAccelerationStructure()
|
|||
VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR };
|
||||
vkGetAccelerationStructureBuildSizesKHR(device->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxInstanceCount, &sizeInfo);
|
||||
|
||||
BufferBuilder tlbufbuilder;
|
||||
tlbufbuilder.setUsage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
tlbufbuilder.setSize(sizeInfo.accelerationStructureSize);
|
||||
tlAccelStructBuffer = tlbufbuilder.create(device.get());
|
||||
|
||||
VkAccelerationStructureKHR tlAccelStructHandle = {};
|
||||
VkAccelerationStructureCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR };
|
||||
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
createInfo.buffer = tlAccelStructBuffer->buffer;
|
||||
createInfo.size = sizeInfo.accelerationStructureSize;
|
||||
VkResult result = vkCreateAccelerationStructureKHR(device->device, &createInfo, nullptr, &tlAccelStructHandle);
|
||||
if (result != VK_SUCCESS)
|
||||
|
|
|
@ -47,6 +47,7 @@ private:
|
|||
std::unique_ptr<VulkanBuffer> tlTransferBuffer;
|
||||
std::unique_ptr<VulkanBuffer> tlScratchBuffer;
|
||||
std::unique_ptr<VulkanBuffer> tlInstanceBuffer;
|
||||
std::unique_ptr<VulkanBuffer> tlAccelStructBuffer;
|
||||
std::unique_ptr<VulkanAccelerationStructure> tlAccelStruct;
|
||||
|
||||
std::unique_ptr<VulkanCommandPool> cmdpool;
|
||||
|
|
|
@ -156,11 +156,14 @@ bool VulkanDevice::supportsDeviceExtension(const char *ext) const
|
|||
void VulkanDevice::createAllocator()
|
||||
{
|
||||
VmaAllocatorCreateInfo allocinfo = {};
|
||||
allocinfo.vulkanApiVersion = VK_API_VERSION_1_2;
|
||||
if (supportsDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) && supportsDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME))
|
||||
allocinfo.flags = VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
|
||||
allocinfo.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
|
||||
allocinfo.physicalDevice = physicalDevice.device;
|
||||
allocinfo.device = device;
|
||||
allocinfo.preferredLargeHeapBlockSize = 64 * 1024 * 1024;
|
||||
allocinfo.instance = instance;
|
||||
if (vmaCreateAllocator(&allocinfo, &allocator) != VK_SUCCESS)
|
||||
throw std::runtime_error("Unable to create allocator");
|
||||
}
|
||||
|
@ -185,11 +188,28 @@ void VulkanDevice::createDevice()
|
|||
queueCreateInfos.push_back(queueCreateInfo);
|
||||
}
|
||||
|
||||
VkPhysicalDeviceRayTracingPipelineFeaturesKHR raytracingFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR };
|
||||
raytracingFeatures.rayTracingPipeline = true;
|
||||
raytracingFeatures.rayTraversalPrimitiveCulling = true;
|
||||
|
||||
VkPhysicalDeviceAccelerationStructureFeaturesKHR deviceAccelFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR };
|
||||
deviceAccelFeatures.accelerationStructure = true;
|
||||
deviceAccelFeatures.pNext = &raytracingFeatures;
|
||||
|
||||
VkPhysicalDeviceBufferDeviceAddressFeatures deviceAddressFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES };
|
||||
deviceAddressFeatures.bufferDeviceAddress = true;
|
||||
deviceAddressFeatures.pNext = &deviceAccelFeatures;
|
||||
|
||||
VkPhysicalDeviceFeatures2 deviceFeatures2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 };
|
||||
deviceFeatures2.features = enabledDeviceFeatures;
|
||||
deviceFeatures2.pNext = &deviceAddressFeatures;
|
||||
|
||||
VkDeviceCreateInfo deviceCreateInfo = {};
|
||||
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
deviceCreateInfo.pNext = &deviceFeatures2;
|
||||
deviceCreateInfo.queueCreateInfoCount = (uint32_t)queueCreateInfos.size();
|
||||
deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data();
|
||||
deviceCreateInfo.pEnabledFeatures = &enabledDeviceFeatures;
|
||||
//deviceCreateInfo.pEnabledFeatures = &enabledDeviceFeatures;
|
||||
deviceCreateInfo.enabledExtensionCount = (uint32_t)enabledDeviceExtensions.size();
|
||||
deviceCreateInfo.ppEnabledExtensionNames = enabledDeviceExtensions.data();
|
||||
deviceCreateInfo.enabledLayerCount = 0;
|
||||
|
@ -255,16 +275,20 @@ void VulkanDevice::createInstance()
|
|||
extensions = getExtensions();
|
||||
enabledExtensions = getPlatformExtensions();
|
||||
|
||||
std::string debugLayer = "VK_LAYER_LUNARG_standard_validation";
|
||||
std::string debugLayer = "VK_LAYER_KHRONOS_validation";
|
||||
bool wantDebugLayer = vk_debug;
|
||||
bool debugLayerFound = false;
|
||||
for (const VkLayerProperties &layer : availableLayers)
|
||||
if (wantDebugLayer)
|
||||
{
|
||||
if (layer.layerName == debugLayer && wantDebugLayer)
|
||||
for (const VkLayerProperties& layer : availableLayers)
|
||||
{
|
||||
enabledValidationLayers.push_back(debugLayer.c_str());
|
||||
enabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
debugLayerFound = true;
|
||||
if (layer.layerName == debugLayer)
|
||||
{
|
||||
enabledValidationLayers.push_back(layer.layerName);
|
||||
enabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
debugLayerFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,8 @@ public:
|
|||
//VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||
VK_KHR_RAY_QUERY_EXTENSION_NAME,
|
||||
VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME,
|
||||
VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME
|
||||
VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME,
|
||||
VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME
|
||||
};
|
||||
std::vector<const char *> optionalDeviceExtensions = {
|
||||
//VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
|
||||
|
|
Loading…
Reference in a new issue