diff --git a/CMakeLists.txt b/CMakeLists.txt index 67b071ee9..155730795 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,7 +84,7 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") elseif(CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang$") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") - set(CMAKE_CXX_FLAGS "-Wall -Werror -Wformat-security -Wno-deprecated-volatile -fPIC") + set(CMAKE_CXX_FLAGS "-Wall -Wformat-security -Wno-deprecated-volatile -fPIC") set(CMAKE_CXX_FLAGS_RELEASE "-O3") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g3 -ggdb3 -Og") set(CMAKE_CXX_FLAGS_DEBUG "-g3 -ggdb3 -O0") @@ -97,7 +97,12 @@ endif() set(PROJECT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(PROJECT_OUTPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bin) -set(CMAKE_INSTALL_RPATH $ORIGIN) +if(APPLE) + set(CMAKE_INSTALL_RPATH "@executable_path;/usr/local/lib") +elseif(UNIX) + set(CMAKE_INSTALL_RPATH "$ORIGIN") +endif() + set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) # Put RUNTIME and LIBRARY outputs into a folder where we can run them without installing diff --git a/assets/scripts/tests/scene-reload.txt b/assets/scripts/tests/scene-reload.txt new file mode 100644 index 000000000..74df1358a --- /dev/null +++ b/assets/scripts/tests/scene-reload.txt @@ -0,0 +1,40 @@ +x.PhysicsFPS 120 +g.LogicFPS 120 +loadscene test1 +screenshot reload-before1.png +stepgraphics +steplogic +stepphysics +stepgraphics 120 +screenshot reload-before2.png +stepgraphics +assert_position test1:animbox 0 1.5 -4.875 + +reloadscene +screenshot reload-after1.png +stepgraphics +assert_position test1:animbox 0 1.5 -4.875 +steplogic +stepphysics +stepgraphics + +reloadscene +reloadscene +reloadscene +reloadscene +screenshot reload-after2.png +stepgraphics +assert_position test1:animbox 0 1.5 -4.875 +steplogic 2700 +stepphysics 2 +stepgraphics 120 +screenshot reload-after3.png +stepgraphics +assert_position test1:animbox 0 1.5 -4.875 +stepphysics 120 +assert_position test1:animbox 0 2 -4.875 +stepphysics 120 +assert_position test1:animbox 0 5 -4.875 +stepgraphics 120 +screenshot reload-after4.png +stepgraphics diff --git a/shaders/lib/util.glsl b/shaders/lib/util.glsl index 31971ef62..c860e881d 100644 --- a/shaders/lib/util.glsl +++ b/shaders/lib/util.glsl @@ -56,6 +56,13 @@ vec2 bilinearMix(vec2 v00, vec2 v10, vec2 v01, vec2 v11, vec2 alpha) { return mix(x1, x2, alpha.y); } +uint FlattenIndex(ivec3 pos, ivec3 gridSize) { + uint x = pos.x; + uint y = pos.y * gridSize.x; + uint z = pos.z * gridSize.x * gridSize.y; + return x + y + z; +} + #include "color_util.glsl" #include "spatial_util.glsl" diff --git a/shaders/lib/voxel_trace_debug.glsl b/shaders/lib/voxel_trace_debug.glsl index 3b986f8fc..9b1bcac81 100644 --- a/shaders/lib/voxel_trace_debug.glsl +++ b/shaders/lib/voxel_trace_debug.glsl @@ -10,16 +10,26 @@ #extension GL_EXT_nonuniform_qualifier : enable +uint FlattenIndex2(ivec3 pos, ivec3 gridSize) { + uint x = pos.x; + uint y = pos.y * gridSize.x; + uint z = pos.z * gridSize.x * gridSize.y; + return x + y + z; +} float GetVoxelNearest(vec3 position, int level, out vec3 radiance) { // uint count = imageLoad(fillCounters, ivec3(position)).r; + // int fillIndex = int(position.x) * voxelInfo.gridSize.y * voxelInfo.gridSize.z + int(position.y) * voxelInfo.gridSize.z + int(position.z); + // uint count = fillCounters[fillIndex]; vec4 radianceData = texelFetch(voxelRadiance, ivec3(position) >> level, level); vec4 normalData = texelFetch(voxelNormals, ivec3(position) >> level, level); // radiance = vec3(length(normalData.xyz / normalData.w)); radiance = radianceData.rgb; // abs(normalData.xyz); + // radiance = vec3(count); return radianceData.a; } float GetVoxelNearest2(vec3 position, vec3 dir, out vec3 radiance) { + uint count = fillCounters[FlattenIndex(ivec3(position), voxelInfo.gridSize)]; //imageLoad(fillCounters, ivec3(position)).r; int axis = DominantAxis(dir); if (axis < 0) { axis = -axis + 2; @@ -28,6 +38,10 @@ float GetVoxelNearest2(vec3 position, vec3 dir, out vec3 radiance) { } vec4 voxelData = texelFetch(voxelLayers[axis], ivec3(position), 0); radiance = voxelData.rgb; + /*float hits = count / 1.0; + radiance.x = hits; + radiance.y = hits; + radiance.z = hits;*/ return voxelData.a; } diff --git a/shaders/vulkan/lib/exposure_state.glsl b/shaders/vulkan/lib/exposure_state.glsl index 4f622499f..1a51d7046 100644 --- a/shaders/vulkan/lib/exposure_state.glsl +++ b/shaders/vulkan/lib/exposure_state.glsl @@ -5,6 +5,6 @@ * If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -buffer ExposureState { +readonly buffer ExposureState { float exposure; }; diff --git a/shaders/vulkan/voxel_debug.frag b/shaders/vulkan/voxel_debug.frag index 860547e2c..621f181ac 100644 --- a/shaders/vulkan/voxel_debug.frag +++ b/shaders/vulkan/voxel_debug.frag @@ -27,13 +27,16 @@ INCLUDE_LAYOUT(binding = 2) #include "lib/exposure_state.glsl" layout(binding = 3) uniform sampler2DArray overlayTex; -layout(binding = 4, r32ui) readonly uniform uimage3D fillCounters; +// layout(binding = 4, r32ui) readonly uniform uimage3D fillCounters; +layout(std430, binding = 4) readonly buffer FillCounters { + uint fillCounters[]; +}; layout(binding = 5) uniform sampler3D voxelRadiance; layout(binding = 6) uniform sampler3D voxelNormals; layout(set = 1, binding = 0) uniform sampler3D voxelLayers[6]; -layout(constant_id = 0) const int DEBUG_MODE = 0; +layout(constant_id = 0) const int DEBUG_MODE = 1; layout(constant_id = 1) const float BLEND_WEIGHT = 0; layout(constant_id = 2) const int VOXEL_MIP = 0; diff --git a/shaders/vulkan/voxel_fill.frag b/shaders/vulkan/voxel_fill.frag index c13ace580..502d8feb4 100644 --- a/shaders/vulkan/voxel_fill.frag +++ b/shaders/vulkan/voxel_fill.frag @@ -42,7 +42,10 @@ layout(set = 2, binding = 0) uniform sampler2D textures[]; #include "../lib/shading.glsl" -layout(binding = 4, r32ui) uniform uimage3D fillCounters; +// layout(binding = 4, r32ui) uniform uimage3D fillCounters; +layout(std430, binding = 4) buffer FillCounters { + uint fillCounters[]; +}; layout(binding = 5, rgba16f) writeonly uniform image3D radianceOut; layout(binding = 6, rgba16f) writeonly uniform image3D normalsOut; @@ -103,8 +106,11 @@ void main() { pixelRadiance = clamp(pixelRadiance, vec3(-8192), vec3(8192)); } - uint bucket = min(FRAGMENT_LIST_COUNT - 1, imageAtomicAdd(fillCounters, ivec3(inVoxelPos), 1)); + // uint bucket = min(FRAGMENT_LIST_COUNT - 1, imageAtomicAdd(fillCounters, ivec3(inVoxelPos), 1)); + int fillIndex = int(inVoxelPos.x) * voxelInfo.gridSize.y * voxelInfo.gridSize.z + int(inVoxelPos.y) * voxelInfo.gridSize.z + int(inVoxelPos.z); + uint bucket = min(FRAGMENT_LIST_COUNT - 1, atomicAdd(fillCounters[fillIndex], 1)); uint index = atomicAdd(fragmentListMetadata[bucket].count, 1); + if (index >= fragmentListMetadata[bucket].capacity) return; if (index % MipmapWorkGroupSize == 0) atomicAdd(fragmentListMetadata[bucket].cmd.x, 1); diff --git a/shaders/vulkan/voxel_fill_layer.comp b/shaders/vulkan/voxel_fill_layer.comp index 30f1947ab..2e4b12bb8 100644 --- a/shaders/vulkan/voxel_fill_layer.comp +++ b/shaders/vulkan/voxel_fill_layer.comp @@ -16,14 +16,14 @@ layout(binding = 0) uniform VoxelStateUniform { VoxelState voxelInfo; }; -layout(std430, binding = 1) buffer VoxelFragmentListMetadata { +layout(std430, binding = 1) readonly buffer VoxelFragmentListMetadata { uint count; uint capacity; uint offset; VkDispatchIndirectCommand cmd; }; -layout(std430, binding = 2) buffer VoxelFragmentList { +layout(std430, binding = 2) readonly buffer VoxelFragmentList { VoxelFragment fragmentLists[]; }; diff --git a/shaders/vulkan/voxel_merge.comp b/shaders/vulkan/voxel_merge.comp index ab9b88528..7ddbde8e4 100644 --- a/shaders/vulkan/voxel_merge.comp +++ b/shaders/vulkan/voxel_merge.comp @@ -14,14 +14,14 @@ layout(local_size_x = 16, local_size_y = 16) in; layout(binding = 0, rgba16f) uniform image3D voxelRadiance; layout(binding = 1, rgba16f) uniform image3D voxelNormals; -layout(std430, binding = 2) buffer VoxelFragmentListMetadata { +layout(std430, binding = 2) readonly buffer VoxelFragmentListMetadata { uint count; uint capacity; uint offset; VkDispatchIndirectCommand cmd; }; -layout(std430, binding = 3) buffer VoxelFragmentList { +layout(std430, binding = 3) readonly buffer VoxelFragmentList { VoxelFragment fragmentLists[]; // Already bound at +offset }; diff --git a/shaders/vulkan/voxel_merge_layer.comp b/shaders/vulkan/voxel_merge_layer.comp index bf114d69a..0573b23e5 100644 --- a/shaders/vulkan/voxel_merge_layer.comp +++ b/shaders/vulkan/voxel_merge_layer.comp @@ -16,14 +16,14 @@ layout(binding = 0) uniform VoxelStateUniform { VoxelState voxelInfo; }; -layout(std430, binding = 1) buffer VoxelFragmentListMetadata { +layout(std430, binding = 1) readonly buffer VoxelFragmentListMetadata { uint count; uint capacity; uint offset; VkDispatchIndirectCommand cmd; }; -layout(std430, binding = 2) buffer VoxelFragmentList { +layout(std430, binding = 2) readonly buffer VoxelFragmentList { VoxelFragment fragmentLists[]; // Already bound at +offset }; diff --git a/shaders/vulkan/voxel_merge_layer_serial.comp b/shaders/vulkan/voxel_merge_layer_serial.comp index 87fee18bf..ca3c862a3 100644 --- a/shaders/vulkan/voxel_merge_layer_serial.comp +++ b/shaders/vulkan/voxel_merge_layer_serial.comp @@ -16,14 +16,14 @@ layout(binding = 0) uniform VoxelStateUniform { VoxelState voxelInfo; }; -layout(std430, binding = 1) buffer VoxelFragmentListMetadata { +layout(std430, binding = 1) readonly buffer VoxelFragmentListMetadata { uint count; uint capacity; uint offset; VkDispatchIndirectCommand cmd; }; -layout(std430, binding = 2) buffer VoxelFragmentList { +layout(std430, binding = 2) readonly buffer VoxelFragmentList { VoxelFragment fragmentLists[]; // Already bound at +offset }; diff --git a/shaders/vulkan/voxel_merge_serial.comp b/shaders/vulkan/voxel_merge_serial.comp index d0941a292..b7138dbc6 100644 --- a/shaders/vulkan/voxel_merge_serial.comp +++ b/shaders/vulkan/voxel_merge_serial.comp @@ -10,26 +10,32 @@ layout(local_size_x = 1, local_size_y = 1) in; #include "../lib/voxel_shared.glsl" +#include "../lib/types_common.glsl" layout(binding = 0, rgba16f) uniform image3D voxelRadiance; layout(binding = 1, rgba16f) uniform image3D voxelNormals; -layout(std430, binding = 2) buffer VoxelFragmentListMetadata { +layout(std430, binding = 2) readonly buffer VoxelFragmentListMetadata { uint count; uint capacity; uint offset; VkDispatchIndirectCommand cmd; }; -layout(std430, binding = 3) buffer VoxelFragmentList { +layout(std430, binding = 3) readonly buffer VoxelFragmentList { VoxelFragment fragmentList[]; }; -layout(binding = 4, r32ui) uniform uimage3D fillCounters; +// layout(binding = 4, r32ui) uniform uimage3D fillCounters; +layout(std430, binding = 4) readonly buffer FillCounters { + uint fillCounters[]; +}; + +layout(binding = 8) uniform VoxelStateUniform { + VoxelState voxelInfo; +}; -#include "../lib/types_common.glsl" #include "../lib/util.glsl" -#include "../lib/voxel_shared.glsl" layout(constant_id = 0) const int FRAGMENT_LIST_COUNT = 1; @@ -41,7 +47,9 @@ void main() { vec4 existingRadiance = imageLoad(voxelRadiance, position); vec4 existingNormal = imageLoad(voxelNormals, position); - uint overflowCount = imageLoad(fillCounters, position).r - FRAGMENT_LIST_COUNT + 1; + // uint overflowCount = imageLoad(fillCounters, position).r - FRAGMENT_LIST_COUNT + 1; + int fillIndex = int(position.x) * voxelInfo.gridSize.y * voxelInfo.gridSize.z + int(position.y) * voxelInfo.gridSize.z + int(position.z); + uint overflowCount = fillCounters[fillIndex] - FRAGMENT_LIST_COUNT + 1; float weight = 1.0f / (FRAGMENT_LIST_COUNT + existingRadiance.w - 1); // isNotLast = true if existingRadiance.w - 1 < overflowCount float isNotLast = 1 - step(overflowCount, existingRadiance.w - 1); diff --git a/src/codegen/gen_common.hh b/src/codegen/gen_common.hh index 863576d5a..42071d189 100644 --- a/src/codegen/gen_common.hh +++ b/src/codegen/gen_common.hh @@ -72,6 +72,7 @@ std::string TypeToString() { auto typeStart = charStart; auto embeddingSignature = EmbedTypeIntoSignature(); + auto structStart = embeddingSignature.find("struct ", charStart); if (structStart == charStart) typeStart += "struct "s.size(); @@ -84,6 +85,7 @@ std::string TypeToString() { auto typeStart = charStart; auto embeddingSignature = EmbedTypeIntoSignature(); + auto enumStart = embeddingSignature.find("enum ", charStart); if (enumStart == charStart) typeStart += "enum "s.size(); auto classStart = embeddingSignature.find("class ", charStart); diff --git a/src/core/console/ConsoleTracy.cc b/src/core/console/ConsoleTracy.cc index ce2d79d27..6a6c4fe0f 100644 --- a/src/core/console/ConsoleTracy.cc +++ b/src/core/console/ConsoleTracy.cc @@ -7,6 +7,7 @@ #include "console/Console.hh" +#include #ifdef _WIN32 #include #else diff --git a/src/core/ecs/EventQueue.cc b/src/core/ecs/EventQueue.cc index 902ff141f..7f33747ab 100644 --- a/src/core/ecs/EventQueue.cc +++ b/src/core/ecs/EventQueue.cc @@ -246,13 +246,13 @@ namespace ecs { return true; } - bool EventQueue::Add(const Event &event, size_t transactionId) { + bool EventQueue::Add(const Event &event, uint64_t transactionId) { AsyncEvent asyncEvent(event.name, event.source, event.data); asyncEvent.transactionId = transactionId; return Add(asyncEvent); } - bool EventQueue::Poll(Event &eventOut, size_t transactionId) { + bool EventQueue::Poll(Event &eventOut, uint64_t transactionId) { bool outputSet = false; while (!outputSet) { State s = state.load(); @@ -291,7 +291,7 @@ namespace ecs { return s.head == s.tail; } - size_t EventQueue::Size() { + uint32_t EventQueue::Size() { State s = state.load(); if (s.head > s.tail) { return s.tail + events.size() - s.head; diff --git a/src/core/ecs/EventQueue.hh b/src/core/ecs/EventQueue.hh index b16358fb0..80962cb8c 100644 --- a/src/core/ecs/EventQueue.hh +++ b/src/core/ecs/EventQueue.hh @@ -251,7 +251,7 @@ namespace ecs { Entity source; sp::AsyncPtr data; - size_t transactionId = 0; + uint64_t transactionId = 0; AsyncEvent() {} AsyncEvent(std::string_view name, const Entity &source, const sp::AsyncPtr &data) @@ -280,16 +280,16 @@ namespace ecs { // Returns false if the queue is full bool Add(const AsyncEvent &event); // Returns false if the queue is full - bool Add(const Event &event, size_t transactionId = 0); + bool Add(const Event &event, uint64_t transactionId = 0); // Returns false if the queue is empty - bool Poll(Event &eventOut, size_t transactionId = 0); + bool Poll(Event &eventOut, uint64_t transactionId = 0); bool Empty(); void Clear(); - size_t Size(); + uint32_t Size(); - size_t Capacity() const { + uint32_t Capacity() const { return events.size(); } diff --git a/src/core/ecs/StructMetadata.hh b/src/core/ecs/StructMetadata.hh index cce2b8eb6..fe97b2c2e 100644 --- a/src/core/ecs/StructMetadata.hh +++ b/src/core/ecs/StructMetadata.hh @@ -69,6 +69,7 @@ namespace ecs { template static inline TypeInfo Lookup() { + // Logf("Lookup: %s", typeid(T).name()); using StrippedT = std::remove_pointer_t>; return TypeInfo{ .typeIndex = GetFieldTypeIndex(typeid(std::conditional_t, T, StrippedT>)), diff --git a/src/core/ecs/components/Events.hh b/src/core/ecs/components/Events.hh index eb0e3704b..8bf957925 100644 --- a/src/core/ecs/components/Events.hh +++ b/src/core/ecs/components/Events.hh @@ -35,8 +35,8 @@ namespace ecs { * A transactionId can be provided to synchronize event visibility with transactions. * If no transactionId is provided, this event will be immediately visible to all transactions. */ - size_t Add(const Event &event, size_t transactionId = 0) const; - size_t Add(const AsyncEvent &event) const; + uint64_t Add(const Event &event, uint64_t transactionId = 0) const; + uint64_t Add(const AsyncEvent &event) const; static bool Poll(Lock> lock, const EventQueueRef &queue, Event &eventOut); robin_hood::unordered_map, sp::StringHash, sp::StringEqual> events; diff --git a/src/game/game/SceneManager.cc b/src/game/game/SceneManager.cc index ad89410ac..c44de6f11 100644 --- a/src/game/game/SceneManager.cc +++ b/src/game/game/SceneManager.cc @@ -12,8 +12,6 @@ #include "assets/JsonHelpers.hh" #include "common/Logging.hh" #include "common/Tracing.hh" -#include "console/Console.hh" -#include "console/ConsoleBindingManager.hh" #include "ecs/EcsImpl.hh" #include "ecs/EntityReferenceManager.hh" #include "ecs/ScriptManager.hh" @@ -23,7 +21,6 @@ #include #include -#include #include #include #include diff --git a/src/graphics/graphics/vulkan/Renderer.cc b/src/graphics/graphics/vulkan/Renderer.cc index bda09b135..3ec4a7a3d 100644 --- a/src/graphics/graphics/vulkan/Renderer.cc +++ b/src/graphics/graphics/vulkan/Renderer.cc @@ -294,7 +294,7 @@ namespace sp::vulkan { if (!view) return {}; view.UpdateViewMatrix(lock, ent); - GPUScene::DrawBufferIDs drawIDs; + GPUScene::DrawBufferIDs drawIDs = {}; if (CVarSortedDraw.Get()) { glm::vec3 viewPos = view.invViewMat * glm::vec4(0, 0, 0, 1); drawIDs = scene.GenerateSortedDrawsForView(graph, viewPos, view.visibilityMask, CVarDrawReverseOrder.Get()); @@ -338,7 +338,8 @@ namespace sp::vulkan { scene.DrawSceneIndirect(cmd, resources.GetBuffer("WarpedVertexBuffer"), resources.GetBuffer(drawIDs.drawCommandsBuffer), - resources.GetBuffer(drawIDs.drawParamsBuffer)); + resources.GetBuffer(drawIDs.drawParamsBuffer), + drawIDs.commandCount); }); return view; } @@ -471,7 +472,8 @@ namespace sp::vulkan { scene.DrawSceneIndirect(cmd, resources.GetBuffer("WarpedVertexBuffer"), resources.GetBuffer(drawIDs.drawCommandsBuffer), - resources.GetBuffer(drawIDs.drawParamsBuffer)); + resources.GetBuffer(drawIDs.drawParamsBuffer), + drawIDs.commandCount); GPUViewState *viewState; viewStateBuf->Map((void **)&viewState); diff --git a/src/graphics/graphics/vulkan/core/CommandContext.cc b/src/graphics/graphics/vulkan/core/CommandContext.cc index 9ce45fbe0..407b4aa05 100644 --- a/src/graphics/graphics/vulkan/core/CommandContext.cc +++ b/src/graphics/graphics/vulkan/core/CommandContext.cc @@ -151,15 +151,15 @@ namespace sp::vulkan { cmd->drawIndirect(*drawCommands, offset, drawCount, stride); } - void CommandContext::DrawIndirectCount(BufferPtr drawCommands, - vk::DeviceSize offset, - BufferPtr countBuffer, - vk::DeviceSize countOffset, - uint32_t maxDrawCount, - uint32_t stride) { - FlushGraphicsState(); - cmd->drawIndirectCount(*drawCommands, offset, *countBuffer, countOffset, maxDrawCount, stride); - } + // void CommandContext::DrawIndirectCount(BufferPtr drawCommands, + // vk::DeviceSize offset, + // BufferPtr countBuffer, + // vk::DeviceSize countOffset, + // uint32_t maxDrawCount, + // uint32_t stride) { + // FlushGraphicsState(); + // cmd->drawIndirectCount(*drawCommands, offset, *countBuffer, countOffset, maxDrawCount, stride); + // } void CommandContext::DrawIndexedIndirect(BufferPtr drawCommands, vk::DeviceSize offset, @@ -169,15 +169,15 @@ namespace sp::vulkan { cmd->drawIndexedIndirect(*drawCommands, offset, drawCount, stride); } - void CommandContext::DrawIndexedIndirectCount(BufferPtr drawCommands, - vk::DeviceSize offset, - BufferPtr countBuffer, - vk::DeviceSize countOffset, - uint32_t maxDrawCount, - uint32_t stride) { - FlushGraphicsState(); - cmd->drawIndexedIndirectCount(*drawCommands, offset, *countBuffer, countOffset, maxDrawCount, stride); - } + // void CommandContext::DrawIndexedIndirectCount(BufferPtr drawCommands, + // vk::DeviceSize offset, + // BufferPtr countBuffer, + // vk::DeviceSize countOffset, + // uint32_t maxDrawCount, + // uint32_t stride) { + // FlushGraphicsState(); + // cmd->drawIndexedIndirectCount(*drawCommands, offset, *countBuffer, countOffset, maxDrawCount, stride); + // } void CommandContext::DrawScreenCover(const ImageViewPtr &view) { SetShaders("screen_cover.vert", "screen_cover.frag"); diff --git a/src/graphics/graphics/vulkan/core/CommandContext.hh b/src/graphics/graphics/vulkan/core/CommandContext.hh index 30ca9eee3..24ba5af64 100644 --- a/src/graphics/graphics/vulkan/core/CommandContext.hh +++ b/src/graphics/graphics/vulkan/core/CommandContext.hh @@ -99,22 +99,22 @@ namespace sp::vulkan { vk::DeviceSize offset, uint32_t drawCount, uint32_t stride = sizeof(VkDrawIndirectCommand)); - void DrawIndirectCount(BufferPtr drawCommands, - vk::DeviceSize offset, - BufferPtr countBuffer, - vk::DeviceSize countOffset, - uint32_t maxDrawCount, - uint32_t stride = sizeof(VkDrawIndirectCommand)); + // void DrawIndirectCount(BufferPtr drawCommands, + // vk::DeviceSize offset, + // BufferPtr countBuffer, + // vk::DeviceSize countOffset, + // uint32_t maxDrawCount, + // uint32_t stride = sizeof(VkDrawIndirectCommand)); void DrawIndexedIndirect(BufferPtr drawCommands, vk::DeviceSize offset, uint32_t drawCount, uint32_t stride = sizeof(VkDrawIndexedIndirectCommand)); - void DrawIndexedIndirectCount(BufferPtr drawCommands, - vk::DeviceSize offset, - BufferPtr countBuffer, - vk::DeviceSize countOffset, - uint32_t maxDrawCount, - uint32_t stride = sizeof(VkDrawIndexedIndirectCommand)); + // void DrawIndexedIndirectCount(BufferPtr drawCommands, + // vk::DeviceSize offset, + // BufferPtr countBuffer, + // vk::DeviceSize countOffset, + // uint32_t maxDrawCount, + // uint32_t stride = sizeof(VkDrawIndexedIndirectCommand)); void DrawScreenCover(const ImageViewPtr &view = nullptr); void DrawScreenCover(const color_alpha_t &color); diff --git a/src/graphics/graphics/vulkan/core/DeviceContext.cc b/src/graphics/graphics/vulkan/core/DeviceContext.cc index 93a0865fc..b569866ad 100644 --- a/src/graphics/graphics/vulkan/core/DeviceContext.cc +++ b/src/graphics/graphics/vulkan/core/DeviceContext.cc @@ -176,17 +176,39 @@ namespace sp::vulkan { } auto physicalDevices = instance.enumeratePhysicalDevices(); + + for (auto &device : physicalDevices) { + auto properties = device.getProperties(); + Logf("Found graphics device: %s %u", properties.deviceName.data(), properties.deviceID); + } + // TODO: Prioritize discrete GPUs and check for capabilities like Geometry/Compute shaders if (physicalDevices.size() > 0) { // TODO: Check device extension support physicalDeviceProperties.pNext = &physicalDeviceDescriptorIndexingProperties; physicalDevices.front().getProperties2(&physicalDeviceProperties); // auto features = device.getFeatures(); - Logf("Using graphics device: %s", physicalDeviceProperties.properties.deviceName.data()); + Logf("Using graphics device: %s %u", + physicalDeviceProperties.properties.deviceName.data(), + physicalDeviceProperties.properties.deviceID); physicalDevice = physicalDevices.front(); } Assert(physicalDevice, "No suitable graphics device found!"); + const auto props = physicalDevice.getFormatProperties(vk::Format::eR32Uint); + + const bool hasStorageImage = (props.optimalTilingFeatures & vk::FormatFeatureFlagBits::eStorageImage) == + vk::FormatFeatureFlagBits::eStorageImage; + + const bool hasStorageImageAtomic = (props.optimalTilingFeatures & + vk::FormatFeatureFlagBits::eStorageImageAtomic) == + vk::FormatFeatureFlagBits::eStorageImageAtomic; + + Logf("VK_FORMAT_R32_UINT optimalTilingFeatures: %s", vk::to_string(props.optimalTilingFeatures).c_str()); + Assert(hasStorageImage, "VK_FORMAT_R32_UINT missing VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT"); + Assert(hasStorageImageAtomic, + "VK_FORMAT_R32_UINT missing VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT (imageAtomicAdd undefined)"); + std::array queueIndex; auto queueFamilies = physicalDevice.getQueueFamilyProperties(); vector queuesUsedCount(queueFamilies.size()); @@ -238,8 +260,8 @@ namespace sp::vulkan { } // currently we have code that assumes the transfer queue family is different from the other queues - Assert(queueFamilyIndex[QUEUE_TYPE_TRANSFER] != queueFamilyIndex[QUEUE_TYPE_GRAPHICS], - "transfer queue family overlaps graphics queue"); + // Assert(queueFamilyIndex[QUEUE_TYPE_TRANSFER] != queueFamilyIndex[QUEUE_TYPE_GRAPHICS], + // "transfer queue family overlaps graphics queue"); std::vector queueInfos; for (uint32_t i = 0; i < queueFamilies.size(); i++) { @@ -252,13 +274,12 @@ namespace sp::vulkan { queueInfos.push_back(queueInfo); } - vector enabledDeviceExtensions = { - VK_KHR_MULTIVIEW_EXTENSION_NAME, - VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, + vector enabledDeviceExtensions = {VK_KHR_MULTIVIEW_EXTENSION_NAME, + // VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME, VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, - }; + "VK_KHR_portability_subset"}; if (enableSwapchain) { enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); @@ -286,14 +307,14 @@ namespace sp::vulkan { physicalDevice.getFeatures2KHR(&deviceFeatures2); const auto &availableDeviceFeatures = deviceFeatures2.features; - Assert(availableDeviceFeatures.fillModeNonSolid, "device must support fillModeNonSolid"); + // Assert(availableDeviceFeatures.fillModeNonSolid, "device must support fillModeNonSolid"); Assert(availableDeviceFeatures.samplerAnisotropy, "device must support samplerAnisotropy"); Assert(availableDeviceFeatures.multiDrawIndirect, "device must support multiDrawIndirect"); Assert(availableDeviceFeatures.multiViewport, "device must support multiViewport"); Assert(availableDeviceFeatures.drawIndirectFirstInstance, "device must support drawIndirectFirstInstance"); Assert(availableDeviceFeatures.shaderInt16, "device must support shaderInt16"); Assert(availableDeviceFeatures.fragmentStoresAndAtomics, "device must support fragmentStoresAndAtomics"); - Assert(availableDeviceFeatures.wideLines, "device must support wideLines"); + // Assert(availableDeviceFeatures.wideLines, "device must support wideLines"); Assert(availableVulkan11Features.multiview, "device must support multiview"); Assert(availableVulkan11Features.shaderDrawParameters, "device must support shaderDrawParameters"); Assert(availableVulkan11Features.storageBuffer16BitAccess, "device must support storageBuffer16BitAccess"); @@ -302,7 +323,7 @@ namespace sp::vulkan { Assert(availableVulkan12Features.shaderOutputViewportIndex, "device must support shaderOutputViewportIndex"); Assert(availableVulkan12Features.shaderOutputLayer, "device must support shaderOutputLayer"); - Assert(availableVulkan12Features.drawIndirectCount, "device must support drawIndirectCount"); + // Assert(availableVulkan12Features.drawIndirectCount, "device must support drawIndirectCount"); Assert(availableVulkan12Features.runtimeDescriptorArray, "device must support runtimeDescriptorArray"); Assert(availableVulkan12Features.descriptorBindingPartiallyBound, "device must support descriptorBindingPartiallyBound"); @@ -316,7 +337,7 @@ namespace sp::vulkan { vk::PhysicalDeviceVulkan12Features enabledVulkan12Features; enabledVulkan12Features.shaderOutputViewportIndex = true; enabledVulkan12Features.shaderOutputLayer = true; - enabledVulkan12Features.drawIndirectCount = true; + // enabledVulkan12Features.drawIndirectCount = true; enabledVulkan12Features.runtimeDescriptorArray = true; enabledVulkan12Features.descriptorBindingPartiallyBound = true; enabledVulkan12Features.descriptorBindingVariableDescriptorCount = true; @@ -334,14 +355,14 @@ namespace sp::vulkan { enabledDeviceFeatures2.pNext = &enabledVulkan11Features; auto &enabledDeviceFeatures = enabledDeviceFeatures2.features; enabledDeviceFeatures.dualSrcBlend = true; - enabledDeviceFeatures.fillModeNonSolid = true; + enabledDeviceFeatures.fillModeNonSolid = false; enabledDeviceFeatures.samplerAnisotropy = true; enabledDeviceFeatures.multiDrawIndirect = true; enabledDeviceFeatures.drawIndirectFirstInstance = true; enabledDeviceFeatures.multiViewport = true; enabledDeviceFeatures.shaderInt16 = true; enabledDeviceFeatures.fragmentStoresAndAtomics = true; - enabledDeviceFeatures.wideLines = true; + enabledDeviceFeatures.wideLines = false; vk::DeviceCreateInfo deviceInfo; deviceInfo.queueCreateInfoCount = queueInfos.size(); @@ -550,6 +571,7 @@ namespace sp::vulkan { if (enableSwapchain) CreateSwapchain(); compositor = std::make_unique(*this, graph); + } catch (const vk::InitializationFailedError &err) { Errorf("Device initialization failed! %s", err.what()); deviceResetRequired = true; @@ -1092,8 +1114,9 @@ namespace sp::vulkan { auto cmd = device.GetFencedCommandContext(type); auto info = GetAccessInfo(access); cmd->ImageBarrier(image, info.imageLayout, info.stageMask, info.accessMask, transferToQueue); - device.PushInFlightObject(image, cmd->Fence()); - auto transferComplete = image->SetPendingCommand(device.GetEmptySemaphore(cmd->Fence()), + auto fence = cmd->Fence(); + device.PushInFlightObject(image, fence); + auto transferComplete = image->SetPendingCommand(device.GetEmptySemaphore(fence), transferToQueue.dstQueueFamilyIndex); if (waitSemaphore) { device.Submit(cmd, {transferComplete}, {waitSemaphore}, {info.stageMask}); @@ -1121,6 +1144,7 @@ namespace sp::vulkan { vk::Format factorFormat = createInfo.format; if (!createInfo.mipLevels) createInfo.mipLevels = genMipmap ? CalculateMipmapLevels(createInfo.extent) : 1; + if (!createInfo.arrayLayers) createInfo.arrayLayers = 1; if (!uploadBuffer) { @@ -1171,6 +1195,7 @@ namespace sp::vulkan { transferToCompute.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; } + ImageViewPtr factorView; { GPUZone(this, factorCmd, "ApplyFactor"); @@ -1186,7 +1211,7 @@ namespace sp::vulkan { factorViewInfo.format = factorFormat; factorViewInfo.mipLevelCount = 1; factorViewInfo.usage = vk::ImageUsageFlagBits::eStorage; - auto factorView = CreateImageView(factorViewInfo); + factorView = CreateImageView(factorViewInfo); factorCmd->SetComputeShader("texture_factor.comp"); factorCmd->SetImageView("texture", factorView); @@ -1207,9 +1232,10 @@ namespace sp::vulkan { factorCmd->Dispatch((createInfo.extent.width + 15) / 16, (createInfo.extent.height + 15) / 16, 1); - PushInFlightObject(factorView, factorCmd->Fence()); } - auto factorComplete = image->SetPendingCommand(GetEmptySemaphore(factorCmd->Fence()), + auto fence = factorCmd->Fence(); + PushInFlightObject(factorView, fence); + auto factorComplete = image->SetPendingCommand(GetEmptySemaphore(fence), transferToCompute.dstQueueFamilyIndex); if (waitSemaphore) { Submit(factorCmd, @@ -1273,8 +1299,9 @@ namespace sp::vulkan { vk::ImageLayout::eTransferDstOptimal, {region}); - PushInFlightObject(stagingBuf, transferCmd->Fence()); - auto transferComplete = image->SetPendingCommand(GetEmptySemaphore(transferCmd->Fence()), + auto fence = transferCmd->Fence(); + PushInFlightObject(stagingBuf, fence); + auto transferComplete = image->SetPendingCommand(GetEmptySemaphore(fence), transferToTransferAsync.dstQueueFamilyIndex); { ZoneScopedN("CopyBufferToImage"); @@ -1380,8 +1407,9 @@ namespace sp::vulkan { vk::PipelineStageFlagBits::eFragmentShader, vk::AccessFlagBits::eShaderRead); } - PushInFlightObject(image, graphicsCmd->Fence()); - auto mipmapComplete = image->SetPendingCommand(GetEmptySemaphore(graphicsCmd->Fence()), + auto fence = graphicsCmd->Fence(); + PushInFlightObject(image, fence); + auto mipmapComplete = image->SetPendingCommand(GetEmptySemaphore(fence), transferToGeneral.dstQueueFamilyIndex); if (waitSemaphore) { Submit(graphicsCmd, {mipmapComplete}, {waitSemaphore}, {vk::PipelineStageFlagBits::eTransfer}); diff --git a/src/graphics/graphics/vulkan/core/Image.hh b/src/graphics/graphics/vulkan/core/Image.hh index c83d3e2f2..f5a935d4c 100644 --- a/src/graphics/graphics/vulkan/core/Image.hh +++ b/src/graphics/graphics/vulkan/core/Image.hh @@ -151,7 +151,7 @@ namespace sp::vulkan { vk::Format format; vk::Extent3D extent; uint32_t mipLevels = 0, arrayLayers = 0; - vk::ImageLayout lastLayout = vk::ImageLayout::eUndefined; + vk::ImageLayout lastLayout = vk::ImageLayout::eGeneral; Access lastAccess = Access::None; vk::ImageUsageFlags usage = {}, declaredUsage = {}; diff --git a/src/graphics/graphics/vulkan/core/Shader.hh b/src/graphics/graphics/vulkan/core/Shader.hh index 58b80db2f..8510472ce 100644 --- a/src/graphics/graphics/vulkan/core/Shader.hh +++ b/src/graphics/graphics/vulkan/core/Shader.hh @@ -21,7 +21,7 @@ namespace sp::vulkan { const uint32_t MAX_BOUND_DESCRIPTOR_SETS = 4; const uint32_t MAX_BINDINGS_PER_DESCRIPTOR_SET = 32; const uint32_t MAX_DESCRIPTOR_SETS_PER_POOL = 16; - const uint32_t MAX_BINDINGS_PER_BINDLESS_DESCRIPTOR_SET = 65535; + const uint32_t MAX_BINDINGS_PER_BINDLESS_DESCRIPTOR_SET = 640; class Model; diff --git a/src/graphics/graphics/vulkan/render_graph/PassBuilder.cc b/src/graphics/graphics/vulkan/render_graph/PassBuilder.cc index 9cabab609..8b6d44285 100644 --- a/src/graphics/graphics/vulkan/render_graph/PassBuilder.cc +++ b/src/graphics/graphics/vulkan/render_graph/PassBuilder.cc @@ -7,6 +7,8 @@ #include "PassBuilder.hh" +#include "graphics/vulkan/render_graph/Resources.hh" + namespace sp::vulkan::render_graph { void PassBuilder::Read(ResourceID id, Access access) { pass.AddAccess(id, access); diff --git a/src/graphics/graphics/vulkan/render_graph/Resources.cc b/src/graphics/graphics/vulkan/render_graph/Resources.cc index 7f237db8e..522f9a143 100644 --- a/src/graphics/graphics/vulkan/render_graph/Resources.cc +++ b/src/graphics/graphics/vulkan/render_graph/Resources.cc @@ -455,7 +455,7 @@ namespace sp::vulkan::render_graph { auto it = frame.resourceNames.begin(); while (it != frame.resourceNames.end()) { if (it->second == id) { - frame.resourceNames.erase(it++); + it = frame.resourceNames.erase(it); } else { it++; } diff --git a/src/graphics/graphics/vulkan/render_passes/Blur.cc b/src/graphics/graphics/vulkan/render_passes/Blur.cc index f99b823fc..7c4744a10 100644 --- a/src/graphics/graphics/vulkan/render_passes/Blur.cc +++ b/src/graphics/graphics/vulkan/render_passes/Blur.cc @@ -36,6 +36,7 @@ namespace sp::vulkan::renderer { auto desc = builder.DeriveImage(sourceID); desc.extent.width = std::max(desc.extent.width / downsample, 1u); desc.extent.height = std::max(desc.extent.height / downsample, 1u); + desc.mipLevels = CalculateMipmapLevels(desc.extent); builder.OutputColorAttachment(0, "", desc, {LoadOp::DontCare, StoreOp::Store}); }) .Execute([sourceID, constants](Resources &resources, CommandContext &cmd) { diff --git a/src/graphics/graphics/vulkan/render_passes/Lighting.cc b/src/graphics/graphics/vulkan/render_passes/Lighting.cc index 90c4489a2..8b29b128c 100644 --- a/src/graphics/graphics/vulkan/render_passes/Lighting.cc +++ b/src/graphics/graphics/vulkan/render_passes/Lighting.cc @@ -436,7 +436,8 @@ namespace sp::vulkan::renderer { scene.DrawSceneIndirect(cmd, resources.GetBuffer("WarpedVertexBuffer"), resources.GetBuffer(drawAllIDs.drawCommandsBuffer), - resources.GetBuffer(drawAllIDs.drawParamsBuffer)); + resources.GetBuffer(drawAllIDs.drawParamsBuffer), + drawAllIDs.commandCount); } }); @@ -478,7 +479,8 @@ namespace sp::vulkan::renderer { scene.DrawSceneIndirect(cmd, resources.GetBuffer("WarpedVertexBuffer"), resources.GetBuffer(drawOpticIDs.drawCommandsBuffer), - resources.GetBuffer(drawOpticIDs.drawParamsBuffer)); + resources.GetBuffer(drawOpticIDs.drawParamsBuffer), + drawOpticIDs.commandCount); } }); diff --git a/src/graphics/graphics/vulkan/render_passes/Outline.cc b/src/graphics/graphics/vulkan/render_passes/Outline.cc index 7bb588c91..acefa72cb 100644 --- a/src/graphics/graphics/vulkan/render_passes/Outline.cc +++ b/src/graphics/graphics/vulkan/render_passes/Outline.cc @@ -42,7 +42,8 @@ namespace sp::vulkan::renderer { scene->DrawSceneIndirect(cmd, resources.GetBuffer("WarpedVertexBuffer"), resources.GetBuffer(drawIDs.drawCommandsBuffer), - resources.GetBuffer(drawIDs.drawParamsBuffer)); + resources.GetBuffer(drawIDs.drawParamsBuffer), + drawIDs.commandCount); }); graph.AddPass("Outlines") @@ -73,7 +74,8 @@ namespace sp::vulkan::renderer { scene->DrawSceneIndirect(cmd, resources.GetBuffer("WarpedVertexBuffer"), resources.GetBuffer(drawIDs.drawCommandsBuffer), - resources.GetBuffer(drawIDs.drawParamsBuffer)); + resources.GetBuffer(drawIDs.drawParamsBuffer), + drawIDs.commandCount); }); } } // namespace sp::vulkan::renderer diff --git a/src/graphics/graphics/vulkan/render_passes/Transparency.cc b/src/graphics/graphics/vulkan/render_passes/Transparency.cc index 9327cf601..1f191fb90 100644 --- a/src/graphics/graphics/vulkan/render_passes/Transparency.cc +++ b/src/graphics/graphics/vulkan/render_passes/Transparency.cc @@ -83,7 +83,8 @@ namespace sp::vulkan::renderer { scene.DrawSceneIndirect(cmd, resources.GetBuffer("WarpedVertexBuffer"), resources.GetBuffer(drawIDs.drawCommandsBuffer), - resources.GetBuffer(drawIDs.drawParamsBuffer)); + resources.GetBuffer(drawIDs.drawParamsBuffer), + drawIDs.commandCount); }); } } // namespace sp::vulkan::renderer diff --git a/src/graphics/graphics/vulkan/render_passes/Voxels.cc b/src/graphics/graphics/vulkan/render_passes/Voxels.cc index ecd53a376..017e4099e 100644 --- a/src/graphics/graphics/vulkan/render_passes/Voxels.cc +++ b/src/graphics/graphics/vulkan/render_passes/Voxels.cc @@ -219,17 +219,22 @@ namespace sp::vulkan::renderer { desc.extent = voxelGridExtents; desc.primaryViewType = vk::ImageViewType::e3D; desc.imageType = vk::ImageType::e3D; - desc.mipLevels = voxelGridMips; - desc.format = vk::Format::eR32Uint; - builder.CreateImage("FillCounters", desc, clearCounters ? Access::TransferWrite : Access::None); + // desc.format = vk::Format::eR32Uint; + // builder.CreateImage("FillCounters", desc, clearCounters ? Access::TransferWrite : Access::None); + desc.mipLevels = voxelGridMips; desc.sampler = SamplerType::TrilinearClampBorder; desc.format = vk::Format::eR16G16B16A16Sfloat; builder.CreateImage("Radiance", desc, clearRadiance ? Access::TransferWrite : Access::None); // desc.format = vk::Format::eR8G8B8A8Snorm; builder.CreateImage("Normals", desc, clearNormals ? Access::TransferWrite : Access::None); + builder.CreateBuffer("FillCounters", + {sizeof(uint32_t), voxelGridExtents.width * voxelGridExtents.height * voxelGridExtents.depth}, + Residency::GPU_ONLY, + clearCounters ? Access::TransferWrite : Access::None); + builder.CreateBuffer("FragmentListMetadata", {sizeof(GPUVoxelFragmentList), MAX_VOXEL_FRAGMENT_LISTS}, Residency::GPU_ONLY, @@ -240,7 +245,8 @@ namespace sp::vulkan::renderer { Residency::GPU_ONLY, Access::None); }) - .Execute([this, clearRadiance, clearCounters, clearNormals](rg::Resources &resources, CommandContext &cmd) { + .Execute([this, clearRadiance, clearCounters, clearNormals, voxelGridExtents](rg::Resources &resources, + CommandContext &cmd) { if (clearRadiance) { auto radianceView = resources.GetImageView("Radiance"); vk::ClearColorValue clear; @@ -254,16 +260,18 @@ namespace sp::vulkan::renderer { {range}); } if (clearCounters) { - auto counterView = resources.GetImageView("FillCounters"); - vk::ClearColorValue clear; - vk::ImageSubresourceRange range; - range.layerCount = 1; - range.levelCount = counterView->MipLevels(); - range.aspectMask = vk::ImageAspectFlagBits::eColor; - cmd.Raw().clearColorImage(*counterView->Image(), - vk::ImageLayout::eTransferDstOptimal, - clear, - {range}); + // auto counterView = resources.GetImageView("FillCounters"); + // vk::ClearColorValue clear; + // vk::ImageSubresourceRange range; + // range.layerCount = 1; + // range.levelCount = counterView->MipLevels(); + // range.aspectMask = vk::ImageAspectFlagBits::eColor; + // cmd.Raw().clearColorImage(*counterView->Image(), + // vk::ImageLayout::eTransferDstOptimal, + // clear, + // {range}); + auto counterBuffer = resources.GetBuffer("FillCounters"); + cmd.Raw().fillBuffer(*counterBuffer, 0, vk::WholeSize, 0); } if (clearNormals) { auto normalsView = resources.GetImageView("Normals"); @@ -321,6 +329,7 @@ namespace sp::vulkan::renderer { builder.Write("FragmentListMetadata", Access::FragmentShaderWrite); builder.Write("FragmentLists", Access::FragmentShaderWrite); + builder.Write("FillCounters", Access::FragmentShaderWrite); builder.Read("WarpedVertexBuffer", Access::VertexBuffer); builder.Read(drawID.drawCommandsBuffer, Access::IndirectBuffer); @@ -366,7 +375,8 @@ namespace sp::vulkan::renderer { cmd.SetUniformBuffer("VoxelStateUniform", resources.GetBuffer("VoxelState")); cmd.SetUniformBuffer("LightData", "LightState"); cmd.SetImageView("shadowMap", "ShadowMap/Linear"); - cmd.SetImageView("fillCounters", resources.GetImageMipView("FillCounters", 0)); + // cmd.SetImageView("fillCounters", resources.GetImageMipView("FillCounters", 0)); + cmd.SetStorageBuffer("FillCounters", "FillCounters"); cmd.SetImageView("radianceOut", resources.GetImageMipView("Radiance", 0)); cmd.SetImageView("normalsOut", resources.GetImageMipView("Normals", 0)); cmd.SetStorageBuffer("VoxelFragmentListMetadata", "FragmentListMetadata"); @@ -395,7 +405,8 @@ namespace sp::vulkan::renderer { scene.DrawSceneIndirect(cmd, resources.GetBuffer("WarpedVertexBuffer"), resources.GetBuffer(drawID.drawCommandsBuffer), - resources.GetBuffer(drawID.drawParamsBuffer)); + resources.GetBuffer(drawID.drawParamsBuffer), + drawID.commandCount); cmd.EndRenderPass(); }); @@ -446,6 +457,7 @@ namespace sp::vulkan::renderer { .Execute([this, i = fragmentListCount - 1](rg::Resources &resources, CommandContext &cmd) { cmd.SetComputeShader("voxel_merge_serial.comp"); cmd.SetShaderConstant(ShaderStage::Compute, "FRAGMENT_LIST_COUNT", fragmentListCount); + cmd.SetUniformBuffer("VoxelStateUniform", resources.GetBuffer("VoxelState")); cmd.SetImageView("voxelRadiance", resources.GetImageMipView("Radiance", 0)); cmd.SetImageView("voxelNormals", resources.GetImageMipView("Normals", 0)); @@ -461,8 +473,10 @@ namespace sp::vulkan::renderer { fragmentListSizes[i].offset * sizeof(GPUVoxelFragment), fragmentListSizes[i].capacity * sizeof(GPUVoxelFragment)); - cmd.SetImageView("fillCounters", resources.GetImageMipView("FillCounters", 0)); + // cmd.SetImageView("fillCounters", resources.GetImageMipView("FillCounters", 0)); + cmd.SetStorageBuffer("FillCounters", "FillCounters"); + cmd.SetUniformBuffer("VoxelStateUniform", "VoxelState"); cmd.Dispatch(1, 1, 1); }); @@ -854,7 +868,8 @@ namespace sp::vulkan::renderer { cmd.SetUniformBuffer("VoxelStateUniform", "VoxelState"); cmd.SetStorageBuffer("ExposureState", "ExposureState"); cmd.SetImageView("overlayTex", resources.LastOutputID()); - cmd.SetImageView("fillCounters", "Voxels/FillCounters"); + // cmd.SetImageView("fillCounters", "Voxels/FillCounters"); + cmd.SetStorageBuffer("FillCounters", "Voxels/FillCounters"); cmd.SetImageView("voxelRadiance", "Voxels/Radiance"); cmd.SetImageView("voxelNormals", "Voxels/Normals"); diff --git a/src/graphics/graphics/vulkan/scene/GPUScene.cc b/src/graphics/graphics/vulkan/scene/GPUScene.cc index e6600b472..f4251a283 100644 --- a/src/graphics/graphics/vulkan/scene/GPUScene.cc +++ b/src/graphics/graphics/vulkan/scene/GPUScene.cc @@ -255,7 +255,9 @@ namespace sp::vulkan { GPUScene::DrawBufferIDs GPUScene::GenerateDrawsForView(rg::RenderGraph &graph, ecs::VisibilityMask viewMask, uint32_t instanceCount) { - DrawBufferIDs bufferIDs; + + return GenerateSortedDrawsForView(graph, glm::vec3(0), viewMask, false, instanceCount); + DrawBufferIDs bufferIDs = {}; graph.AddPass("GenerateDrawsForView") .Build([&](rg::PassBuilder &builder) { @@ -282,6 +284,17 @@ namespace sp::vulkan { Residency::GPU_ONLY, Access::ComputeShaderWrite); bufferIDs.drawParamsBuffer = drawParams.id; + + bufferIDs.commandCount = 0; + for (size_t i = 0; i < renderables.size(); i++) { + auto &renderable = renderables[i]; + if (((ecs::VisibilityMask)renderable.visibilityMask & viewMask) != viewMask) continue; + + auto mesh = meshes[i].lock(); + if (!mesh || !mesh->CheckReady()) continue; + + bufferIDs.commandCount += mesh->PrimitiveCount(); + } }) .Execute([this, viewMask, bufferIDs, instanceCount](rg::Resources &resources, CommandContext &cmd) { cmd.SetComputeShader("generate_draws_for_view.comp"); @@ -311,7 +324,7 @@ namespace sp::vulkan { ecs::VisibilityMask viewMask, bool reverseSort, uint32_t instanceCount) { - DrawBufferIDs bufferIDs; + DrawBufferIDs bufferIDs = {}; graph.AddPass("GenerateSortedDrawsForView") .Build([&](rg::PassBuilder &builder) { @@ -326,6 +339,17 @@ namespace sp::vulkan { Residency::CPU_TO_GPU, Access::HostWrite); bufferIDs.drawParamsBuffer = drawParams.id; + + bufferIDs.commandCount = 0; + for (size_t i = 0; i < renderables.size(); i++) { + auto &renderable = renderables[i]; + if (((ecs::VisibilityMask)renderable.visibilityMask & viewMask) != viewMask) continue; + + auto mesh = meshes[i].lock(); + if (!mesh || !mesh->CheckReady()) continue; + + bufferIDs.commandCount += mesh->PrimitiveCount(); + } }) .Execute([this, viewMask, viewPosition, bufferIDs, instanceCount, reverseSort](rg::Resources &resources, CommandContext &cmd) { @@ -402,8 +426,13 @@ namespace sp::vulkan { void GPUScene::DrawSceneIndirect(CommandContext &cmd, BufferPtr vertexBuffer, BufferPtr drawCommandsBuffer, - BufferPtr drawParamsBuffer) { - if (vertexCount == 0) return; + BufferPtr drawParamsBuffer, + size_t commandCount) { + if (vertexCount == 0 || !drawCommandsBuffer) return; + Assertf(commandCount <= drawCommandsBuffer->ArraySize(), + "GPUScene::DrawSceneIndirect called with too many commands: %llu/%llu", + commandCount, + drawParamsBuffer->ArraySize()); cmd.SetBindlessDescriptors(2, textures.GetDescriptorSet()); @@ -412,11 +441,12 @@ namespace sp::vulkan { cmd.Raw().bindVertexBuffers(0, {*vertexBuffer}, {0}); if (drawParamsBuffer) cmd.SetStorageBuffer(1, 0, drawParamsBuffer); - cmd.DrawIndexedIndirectCount(drawCommandsBuffer, - sizeof(uint32_t), - drawCommandsBuffer, - 0, - drawCommandsBuffer->ArraySize()); + // cmd.DrawIndexedIndirectCount(drawCommandsBuffer, + // sizeof(uint32_t), + // drawCommandsBuffer, + // 0, + // drawCommandsBuffer->ArraySize()); + cmd.DrawIndexedIndirect(drawCommandsBuffer, sizeof(uint32_t), commandCount); } void GPUScene::AddGeometryWarp(rg::RenderGraph &graph) { diff --git a/src/graphics/graphics/vulkan/scene/GPUScene.hh b/src/graphics/graphics/vulkan/scene/GPUScene.hh index 86b1fae9c..f82949c2e 100644 --- a/src/graphics/graphics/vulkan/scene/GPUScene.hh +++ b/src/graphics/graphics/vulkan/scene/GPUScene.hh @@ -95,6 +95,7 @@ namespace sp::vulkan { struct DrawBufferIDs { rg::ResourceID drawCommandsBuffer; // first 4 bytes are the number of draws rg::ResourceID drawParamsBuffer = 0; + size_t commandCount = 0; }; DrawBufferIDs GenerateDrawsForView(rg::RenderGraph &graph, @@ -111,7 +112,8 @@ namespace sp::vulkan { void DrawSceneIndirect(CommandContext &cmd, BufferPtr vertexBuffer, BufferPtr drawCommandsBuffer, - BufferPtr drawParamsBuffer); + BufferPtr drawParamsBuffer, + size_t commandCount); void AddGeometryWarp(rg::RenderGraph &graph); diff --git a/src/main/glfw/GlfwInputHandler.cc b/src/main/glfw/GlfwInputHandler.cc index 7aa08dab1..1b0f967e1 100644 --- a/src/main/glfw/GlfwInputHandler.cc +++ b/src/main/glfw/GlfwInputHandler.cc @@ -98,7 +98,13 @@ namespace sp { auto handler = static_cast(glfwGetWindowUserPointer(window)); Assert(handler, "MouseMoveCallback occured without valid context"); - sp_send_input_vec2(handler->ctx, (uint64_t)handler->mouse, INPUT_EVENT_MOUSE_POSITION.c_str(), xPos, yPos); + glm::vec2 monitorScale; + glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &monitorScale.x, &monitorScale.y); + sp_send_input_vec2(handler->ctx, + (uint64_t)handler->mouse, + INPUT_EVENT_MOUSE_POSITION.c_str(), + xPos * monitorScale.x, + yPos * monitorScale.y); int mouseMode = glfwGetInputMode(window, GLFW_CURSOR); if (!glm::any(glm::isinf(handler->prevMousePos)) && handler->prevMouseMode == mouseMode) { diff --git a/src/main/glfw/MainGlfw.cc b/src/main/glfw/MainGlfw.cc index 9856f43f4..838e944f9 100644 --- a/src/main/glfw/MainGlfw.cc +++ b/src/main/glfw/MainGlfw.cc @@ -207,6 +207,8 @@ int main(int argc, char **argv) { extensions.emplace_back(requiredExtensions[i]); } + extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + #ifndef SP_GRAPHICS_SUPPORT_HEADLESS // Create window and surface glm::ivec2 initialSize = glm::ivec2(0); @@ -247,7 +249,7 @@ int main(int argc, char **argv) { createInfo.setPNext((VkDebugUtilsMessengerCreateInfoEXT *)&debugInfo); #endif - + createInfo.flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR; vk::Instance vkInstance = vk::createInstance(createInfo); sp_graphics_set_vulkan_instance(GameGraphics, vkInstance, [](sp_graphics_ctx_t *graphics, VkInstance instance) { if (instance) ((vk::Instance)instance).destroy(); diff --git a/src/scripts/guis/SignalDisplayGui.cc b/src/scripts/guis/SignalDisplayGui.cc index 7717b3e23..a889c0247 100644 --- a/src/scripts/guis/SignalDisplayGui.cc +++ b/src/scripts/guis/SignalDisplayGui.cc @@ -63,8 +63,10 @@ namespace sp::scripts { void Destroy(ScriptState &state) { Debugf("Destroying signal display: %llu", state.GetInstanceId()); - ImGui::DestroyContext(imCtx); - imCtx = nullptr; + if (imCtx) { + ImGui::DestroyContext(imCtx); + imCtx = nullptr; + } } bool PreDefine(ScriptState &state, Entity ent) {