diff --git a/CMakeLists.txt b/CMakeLists.txt index 6557c79..6c02877 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -168,6 +168,8 @@ set( SOURCES src/lightmap/vulkanobjects.h src/lightmap/vulkanbuilders.cpp src/lightmap/vulkanbuilders.h + src/lightmap/stacktrace.cpp + src/lightmap/stacktrace.h src/lightmap/gpuraytracer.cpp src/lightmap/gpuraytracer.h src/math/angle.cpp diff --git a/src/lightmap/gpuraytracer.cpp b/src/lightmap/gpuraytracer.cpp index df0677d..e13c802 100644 --- a/src/lightmap/gpuraytracer.cpp +++ b/src/lightmap/gpuraytracer.cpp @@ -9,205 +9,23 @@ #include "framework/templates.h" #include "framework/halffloat.h" #include "vulkanbuilders.h" +#include "stacktrace.h" #include #include #include #include -#ifdef WIN32 -#include -#else -#include -#include -#include -#include -#include -#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(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 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() { auto printLog = [](const char* typestr, const std::string& msg) { printf("\n[%s] %s\n", typestr, msg.c_str()); - std::string callstack = CaptureStackTraceText(0, true); + std::string callstack = CaptureStackTraceText(0); if (!callstack.empty()) printf("%s\n", callstack.c_str()); }; @@ -615,7 +433,7 @@ void GPURaytracer::CreateTopLevelAccelerationStructure() instance.instanceCustomIndex = 0; instance.accelerationStructureReference = blAccelStructAddress; instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; - instance.mask = 0xffffffff; + instance.mask = 0xff; instance.instanceShaderBindingTableRecordOffset = 0; BufferBuilder tbuilder; @@ -698,40 +516,6 @@ void GPURaytracer::CreateTopLevelAccelerationStructure() void GPURaytracer::CreateShaders() { - std::string code = R"( - #version 460 - #extension GL_EXT_ray_tracing : require - - struct hitPayload - { - vec3 hitValue; - }; - - layout(location = 0) rayPayloadEXT hitPayload prd; - layout(set = 0, binding = 0) uniform accelerationStructureEXT acc; - layout(set = 0, binding = 1, rgba32f) uniform image2D image; - layout(set = 0, binding = 2) uniform Uniforms - { - mat4 viewInverse; - mat4 projInverse; - }; - - void main() - { - const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); - const vec2 inUV = pixelCenter / vec2(gl_LaunchSizeEXT.xy); - vec2 d = inUV * 2.0 - 1.0; - - vec4 origin = viewInverse * vec4(0, 0, 0, 1); - vec4 target = projInverse * vec4(d.x, d.y, 1, 1); - vec4 direction = viewInverse * vec4(normalize(target.xyz), 0); - - traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin.xyz, 0.001, direction.xyz, 10000.0, 0); - - imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(prd.hitValue, 1.0)); - } - )"; - static bool firstCall = true; if (firstCall) { @@ -739,7 +523,91 @@ void GPURaytracer::CreateShaders() firstCall = false; } - ShaderBuilder builder; - builder.setRayGenShader(code); - shaderRayGen = builder.create(device.get()); + { + std::string code = R"( + #version 460 + #extension GL_EXT_ray_tracing : require + + struct hitPayload + { + vec3 hitValue; + }; + + layout(location = 0) rayPayloadEXT hitPayload payload; + + layout(set = 0, binding = 0) uniform accelerationStructureEXT acc; + layout(set = 0, binding = 1, rgba32f) uniform image2D image; + + layout(set = 0, binding = 2) uniform Uniforms + { + mat4 viewInverse; + mat4 projInverse; + }; + + void main() + { + const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); + const vec2 inUV = pixelCenter / vec2(gl_LaunchSizeEXT.xy); + vec2 d = inUV * 2.0 - 1.0; + + vec4 origin = viewInverse * vec4(0, 0, 0, 1); + vec4 target = projInverse * vec4(d.x, d.y, 1, 1); + vec4 direction = viewInverse * vec4(normalize(target.xyz), 0); + + traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin.xyz, 0.001, direction.xyz, 10000.0, 0); + + imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(payload.hitValue, 1.0)); + } + )"; + + ShaderBuilder builder; + builder.setRayGenShader(code); + shaderRayGen = builder.create(device.get()); + } + + { + std::string code = R"( + #version 460 + #extension GL_EXT_ray_tracing : require + + struct hitPayload + { + vec3 hitValue; + }; + + layout(location = 0) rayPayloadEXT hitPayload payload; + + void main() + { + payload.hitValue = vec3(1.0); + } + )"; + + ShaderBuilder builder; + builder.setMissShader(code); + shaderMiss = builder.create(device.get()); + } + + { + std::string code = R"( + #version 460 + #extension GL_EXT_ray_tracing : require + + struct hitPayload + { + vec3 hitValue; + }; + + layout(location = 0) rayPayloadEXT hitPayload payload; + + void main() + { + payload.hitValue = vec3(0.0); + } + )"; + + ShaderBuilder builder; + builder.setClosestHitShader(code); + shaderClosestHit = builder.create(device.get()); + } } diff --git a/src/lightmap/gpuraytracer.h b/src/lightmap/gpuraytracer.h index ca44b17..dad952c 100644 --- a/src/lightmap/gpuraytracer.h +++ b/src/lightmap/gpuraytracer.h @@ -52,6 +52,8 @@ private: std::unique_ptr tlAccelStruct; std::unique_ptr shaderRayGen; + std::unique_ptr shaderMiss; + std::unique_ptr shaderClosestHit; std::unique_ptr cmdpool; std::unique_ptr cmdbuffer; diff --git a/src/lightmap/stacktrace.cpp b/src/lightmap/stacktrace.cpp new file mode 100644 index 0000000..09c38d9 --- /dev/null +++ b/src/lightmap/stacktrace.cpp @@ -0,0 +1,184 @@ + +#include "stacktrace.h" + +#ifdef WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#endif + +#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(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) +{ + void* frames[32]; + int numframes = CaptureStackTrace(32, frames); + + NativeSymbolResolver nativeSymbols; + + std::string s; + for (int i = framesToSkip + 1; i < numframes; i++) + { + s += nativeSymbols.GetName(frames[i]); + } + return s; +} diff --git a/src/lightmap/stacktrace.h b/src/lightmap/stacktrace.h new file mode 100644 index 0000000..7bc8409 --- /dev/null +++ b/src/lightmap/stacktrace.h @@ -0,0 +1,6 @@ + +#pragma once + +#include + +std::string CaptureStackTraceText(int framesToSkip); diff --git a/src/lightmap/vulkanbuilders.cpp b/src/lightmap/vulkanbuilders.cpp index aefebc4..fa9ce59 100644 --- a/src/lightmap/vulkanbuilders.cpp +++ b/src/lightmap/vulkanbuilders.cpp @@ -135,8 +135,6 @@ void ShaderBuilder::setAnyHitShader(const std::string &c) { code = c; stage = ES void ShaderBuilder::setClosestHitShader(const std::string &c) { code = c; stage = EShLanguage::EShLangClosestHit; } void ShaderBuilder::setMissShader(const std::string &c) { code = c; stage = EShLanguage::EShLangMiss; } void ShaderBuilder::setCallableShader(const std::string &c) { code = c; stage = EShLanguage::EShLangCallable; } -//void ShaderBuilder::setTaskShader(const std::string &c) { code = c; stage = EShLanguage::EShLangTaskNV; } -//void ShaderBuilder::setMeshShader(const std::string &c) { code = c; stage = EShLanguage::EShLangMeshNV; } std::unique_ptr ShaderBuilder::create(VulkanDevice *device) { diff --git a/src/lightmap/vulkanbuilders.h b/src/lightmap/vulkanbuilders.h index 3417ff8..adb0683 100644 --- a/src/lightmap/vulkanbuilders.h +++ b/src/lightmap/vulkanbuilders.h @@ -121,14 +121,12 @@ public: void setClosestHitShader(const std::string &code); void setMissShader(const std::string &code); void setCallableShader(const std::string &code); - //void setTaskShader(const std::string &code); - //void setMeshShader(const std::string &code); std::unique_ptr create(VulkanDevice *device); private: std::string code; - int stage; + int stage = 0; }; class AccelerationStructureBuilderNV