diff --git a/Makefile b/Makefile index b713f53e..f3236628 100644 --- a/Makefile +++ b/Makefile @@ -15,18 +15,18 @@ UF_LIBS = # EXT_LIBS = -lpng16 -lz -lassimp -lsfml-main -lsfml-system -lsfml-window -lsfml-graphics -llua52 # EXT_LIBS = -lpng16 -lz -lassimp -ljsoncpp -lopenal32 -lalut -lvorbis -lvorbisfile -logg -lfreetype EXT_LIBS = -#FLAGS = -std=c++0x -Wall -g -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENGL -DUF_USE_GLEW -FLAGS = -Og -std=c++17 -g -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN -DGLM_ENABLE_EXPERIMENTAL -DUF_USE_JSON -DUF_USE_OPENAL -DUF_USE_VORBIS -DUF_USE_FREETYPE -DUSE_OPENVR_MINGW +#FLAGS = -std=c++0x -Wall -g -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENGL -DUF_USE_GLEW -DUF_USE_DISCORD +FLAGS = -fdiagnostics-color=always -Og -std=c++17 -g -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN -DGLM_ENABLE_EXPERIMENTAL -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENAL -DUF_USE_VORBIS -DUF_USE_FREETYPE -DUSE_OPENVR_MINGW #-march=native LIB_NAME = uf EXT_LIB_NAME = ext -#VULKAN_WIN64_SDK_PATH = /cygdrive/c/VulkanSDK/1.1.101.0/ -#VULKAN_WIN64_SDK_PATH = /cygdrive/c/VulkanSDK/1.1.108.0/ -#VULKAN_WIN64_SDK_PATH = /cygdrive/c/VulkanSDK/1.1.114.0/ -#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.2.141.2/ -VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.2.154.0/ +#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.1.101.0/ +#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.1.108.0/ +#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.1.114.0/ +VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.2.141.2/ +#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.2.154.0/ WIN64_CC = /opt/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/mingw64/bin/g++ WIN64_GLSL_VALIDATOR = $(VULKAN_WIN64_SDK_PATH)/Bin32/glslangValidator # Base Engine's DLL @@ -35,7 +35,7 @@ WIN64_LB_FLAGS = $(ENGINE_LIB_DIR)/win64 WIN64_DEPS = -lgdi32 -lvulkan -lspirv-cross -lpng -lz -ljsoncpp -lopenal -lalut -lvorbis -lvorbisfile -logg -lfreetype -lncursesw -lcurl -ldiscord_game_sdk -lopenvr_api #WIN64_DEPS = -lvulkan -lncursesw WIN64_LINKS = $(UF_LIBS) $(EXT_LIBS) $(WIN64_DEPS) -WIN64_FLAGS = $(FLAGS) -g +WIN64_FLAGS = $(FLAGS) #-Wl,-subsystem,windows WIN64_LIB_DIR = $(ENGINE_LIB_DIR)/win64/ diff --git a/bin/data/shaders/display.subpass.frag.glsl b/bin/data/shaders/display.subpass.frag.glsl index ac88c716..ab693a64 100644 --- a/bin/data/shaders/display.subpass.frag.glsl +++ b/bin/data/shaders/display.subpass.frag.glsl @@ -4,8 +4,7 @@ layout (constant_id = 0) const uint LIGHTS = 32; layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerAlbedo; layout (input_attachment_index = 0, binding = 2) uniform subpassInput samplerNormal; -layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerPosition; -// layout (input_attachment_index = 0, binding = 4) uniform subpassInput samplerDepth; +layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerDepth; layout (binding = 5) uniform sampler2D samplerShadows[LIGHTS]; /* layout (std140, binding = 6) buffer Palette { @@ -347,11 +346,34 @@ void main() { vec4 albedoSpecular = subpassLoad(samplerAlbedo); vec3 fragColor = albedoSpecular.rgb * ubo.ambient.rgb; normal.eye = subpassLoad(samplerNormal).rgb; +/* position.eye = subpassLoad(samplerPosition).rgb; { mat4 iView = inverse( ubo.matrices.view[inPushConstantPass] ); vec4 positionWorld = iView * vec4(position.eye, 1); position.world = positionWorld.xyz; } +*/ + { + mat4 iProj = inverse( ubo.matrices.projection[inPushConstantPass] ); + mat4 iView = inverse( ubo.matrices.view[inPushConstantPass] ); + + float depth = subpassLoad(samplerDepth).r; + + if ( false ) { + depth /= 0.00526; + outFragColor.rgb = vec3( 1 - depth ); + outFragColor.a = 1; + return; + } + + vec4 positionClip = vec4(inUv * 2.0 - 1.0, depth, 1.0); + vec4 positionEye = iProj * positionClip; + positionEye /= positionEye.w; + position.eye = positionEye.xyz; + + vec4 positionWorld = iView * positionEye; + position.world = positionWorld.xyz; + } float litFactor = 1.0; for ( uint i = 0, shadowMap = 0; i < LIGHTS; ++i ) { Light light = ubo.lights[i]; diff --git a/bin/data/shaders/display.subpass.stereo.frag.glsl b/bin/data/shaders/display.subpass.stereo.frag.glsl new file mode 100644 index 00000000..c34eaa4d --- /dev/null +++ b/bin/data/shaders/display.subpass.stereo.frag.glsl @@ -0,0 +1,380 @@ +#version 450 + +layout (constant_id = 0) const uint LIGHTS = 32; + +layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerAlbedo; +layout (input_attachment_index = 0, binding = 2) uniform subpassInput samplerNormal; +layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerPosition; +layout (binding = 5) uniform sampler2D samplerShadows[LIGHTS]; +/* +layout (std140, binding = 6) buffer Palette { + vec4 palette[]; +}; +*/ +layout (location = 0) in vec2 inUv; +layout (location = 1) in flat uint inPushConstantPass; + +layout (location = 0) out vec4 outFragColor; + +/* +const vec2 poissonDisk[4] = vec2[]( + vec2( -0.94201624, -0.39906216 ), + vec2( 0.94558609, -0.76890725 ), + vec2( -0.094184101, -0.92938870 ), + vec2( 0.34495938, 0.29387760 ) +); +*/ +vec2 poissonDisk[16] = vec2[]( + vec2( -0.94201624, -0.39906216 ), + vec2( 0.94558609, -0.76890725 ), + vec2( -0.094184101, -0.92938870 ), + vec2( 0.34495938, 0.29387760 ), + vec2( -0.91588581, 0.45771432 ), + vec2( -0.81544232, -0.87912464 ), + vec2( -0.38277543, 0.27676845 ), + vec2( 0.97484398, 0.75648379 ), + vec2( 0.44323325, -0.97511554 ), + vec2( 0.53742981, -0.47373420 ), + vec2( -0.26496911, -0.41893023 ), + vec2( 0.79197514, 0.19090188 ), + vec2( -0.24188840, 0.99706507 ), + vec2( -0.81409955, 0.91437590 ), + vec2( 0.19984126, 0.78641367 ), + vec2( 0.14383161, -0.14100790 ) +); + +struct Light { + vec3 position; + float radius; + vec3 color; + float power; + int type; + float depthBias; + vec2 padding; + mat4 view; + mat4 projection; +}; + +struct Matrices { + mat4 view[2]; + mat4 projection[2]; +}; + +struct Space { + vec3 eye; + vec3 world; +} position, normal, view; + +struct Fog { + vec4 color; + vec2 range; + vec2 padding; +}; + +struct Mode { + uint type; + uint scalar; + vec2 padding; + vec4 parameters; +}; + +layout (binding = 0) uniform UBO { + Matrices matrices; + vec3 ambient; + float kexp; + Mode mode; + Fog fog; + Light lights[LIGHTS]; +} ubo; + +void fog( inout vec3 i, float scale ) { + if ( ubo.fog.range.x == 0 || ubo.fog.range.y == 0 ) return; + + vec3 color = ubo.fog.color.rgb; + float inner = ubo.fog.range.x; + float outer = ubo.fog.range.y * scale; + float distance = length(-position.eye); + float factor = (distance - inner) / (outer - inner); + factor = clamp( factor, 0.0, 1.0 ); + + i = mix(i.rgb, color, factor); +} + +void phong( Light light, vec4 albedoSpecular, inout vec3 i ) { + vec3 Ls = vec3(1.0, 1.0, 1.0); // light specular + vec3 Ld = light.color; // light color + vec3 La = vec3(1.0, 1.0, 1.0); + + vec3 Ks = vec3(albedoSpecular.a); // material specular + vec3 Kd = albedoSpecular.rgb; // material diffuse + vec3 Ka = vec3(1.0, 1.0, 1.0); + + float Kexp = ubo.kexp; + + vec3 L = light.position.xyz - position.eye; + float dist = length(L); + + if ( light.radius > 0.001 && light.radius < dist ) return; + + vec3 D = normalize(L); + float d_dot = max(dot( D, normal.eye ), 0.0); + + vec3 R = reflect( -D, normal.eye ); + vec3 S = normalize(-position.eye); + float s_factor = pow( max(dot( R, S ), 0.0), Kexp ); + if ( Kexp < 0.0001 ) s_factor = 0; + + float attenuation = 1; + if ( light.radius > 0.0001 ) + attenuation = clamp( light.radius / (pow(dist, 2.0) + 1.0), 0.0, 1.0 ); + + vec3 Ia = La * Ka; + vec3 Id = Ld * Kd * d_dot * attenuation; + vec3 Is = Ls * Ks * s_factor * attenuation; + + i += Id * light.power + Is; +} + +float random(vec3 seed, int i){ + vec4 seed4 = vec4(seed,i); + float dot_product = dot(seed4, vec4(12.9898,78.233,45.164,94.673)); + return fract(sin(dot_product) * 43758.5453); +} + +float shadowFactor( Light light, uint shadowMap ) { + vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0); + positionClip.xyz /= positionClip.w; + + if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0; + if ( positionClip.y < -1 || positionClip.y >= 1 ) return 0.0; + if ( positionClip.z <= 0 || positionClip.z >= 1 ) return 0.0; + + float factor = 1.0; + + // spot light + if ( light.type == 2 || light.type == 3 ) { + float dist = length( positionClip.xy ); + if ( dist > 0.5 ) return 0.0; + + // spot light with attenuation + if ( light.type == 3 ) { + factor = 1.0 - (pow(dist * 2,2.0)); + } + } + + vec2 uv = positionClip.xy * 0.5 + 0.5; + float bias = light.depthBias; + if ( false ) { + float cosTheta = clamp(dot(normal.eye, normalize(light.position.xyz - position.eye)), 0, 1); + bias = clamp(bias * tan(acos(cosTheta)), 0, 0.01); + } + + float eyeDepth = positionClip.z; + int samples = poissonDisk.length(); + if ( samples <= 1 ) { + return eyeDepth < texture(samplerShadows[shadowMap], uv).r - bias ? 0.0 : factor; + } + for ( int i = 0; i < samples; ++i ) { + // int index = i; + // int index = int( float(samples) * random(gl_FragCoord.xyy, i) ) % samples; + int index = int( float(samples) * random(floor(position.world.xyz * 1000.0), i)) % samples; + float lightDepth = texture(samplerShadows[shadowMap], uv + poissonDisk[index] / 700.0 ).r; + if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples; + } + return factor; +} +vec3 hslToRgb(vec3 HSL) { + vec3 RGB; { + float H = HSL.x; + float R = abs(H * 6 - 3) - 1; + float G = 2 - abs(H * 6 - 2); + float B = 2 - abs(H * 6 - 4); + RGB = clamp(vec3(R,G,B), 0, 1); + } + float C = (1 - abs(2 * HSL.z - 1)) * HSL.y; + return (RGB - 0.5) * C + HSL.z; +} +vec3 rgbToHsl(vec3 RGB) { + float Epsilon = 1e-10; + vec3 HCV; { + vec4 P = (RGB.g < RGB.b) ? vec4(RGB.bg, -1.0, 2.0/3.0) : vec4(RGB.gb, 0.0, -1.0/3.0); + vec4 Q = (RGB.r < P.x) ? vec4(P.xyw, RGB.r) : vec4(RGB.r, P.yzx); + float C = Q.x - min(Q.w, Q.y); + float H = abs((Q.w - Q.y) / (6 * C + Epsilon) + Q.z); + HCV = vec3(H, C, Q.x); + } + float L = HCV.z - HCV.y * 0.5; + float S = HCV.y / (1 - abs(L * 2 - 1) + Epsilon); + return vec3(HCV.x, S, L); +} + +float hueDistance(float h1, float h2) { + float diff = abs((h1 - h2)); + return min(abs((1.0 - diff)), diff); +} +const float lightnessSteps = 4.0; +float lightnessStep(float l) { + return floor((0.5 + l * lightnessSteps)) / lightnessSteps; +} +const int indexMatrix16x16[256] = int[](0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255, + 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127, + 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223, + 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95, + 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247, + 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119, + 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215, + 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87, + 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253, + 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125, + 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221, + 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93, + 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245, + 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117, + 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213, + 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85); +float indexValue16x16( float scale ) { + int x = int(mod(gl_FragCoord.x * scale, 16)); + int y = int(mod(gl_FragCoord.y * scale, 16)); + return indexMatrix16x16[(x + y * 16)] / 256.0; +} +const int indexMatrix8x8[64] = int[](0, 32, 8, 40, 2, 34, 10, 42, + 48, 16, 56, 24, 50, 18, 58, 26, + 12, 44, 4, 36, 14, 46, 6, 38, + 60, 28, 52, 20, 62, 30, 54, 22, + 3, 35, 11, 43, 1, 33, 9, 41, + 51, 19, 59, 27, 49, 17, 57, 25, + 15, 47, 7, 39, 13, 45, 5, 37, + 63, 31, 55, 23, 61, 29, 53, 21); +float indexValue8x8( float scale ) { + int x = int(mod(gl_FragCoord.x * scale, 8)); + int y = int(mod(gl_FragCoord.y * scale, 8)); + return indexMatrix8x8[(x + y * 8)] / 64.0; +} +const int indexMatrix4x4[16] = int[](0, 8, 2, 10, + 12, 4, 14, 6, + 3, 11, 1, 9, + 15, 7, 13, 5); +float indexValue4x4( float scale ) { + int x = int(mod(gl_FragCoord.x * scale, 4)); + int y = int(mod(gl_FragCoord.y * scale, 4)); + return indexMatrix4x4[(x + y * 4)] / 16.0; +} +vec3[2] closestColors(float hue) { + vec3 ret[2]; + vec3 closest = vec3(-2, 0, 0); + vec3 secondClosest = vec3(-2, 0, 0); + vec3 temp; +/* + for (int i = 0; i < palette.length(); ++i) { + temp = rgbToHsl(palette[i].rgb); + float tempDistance = hueDistance(temp.x, hue); + if (tempDistance < hueDistance(closest.x, hue)) { + secondClosest = closest; + closest = temp; + } else { + if (tempDistance < hueDistance(secondClosest.x, hue)) { + secondClosest = temp; + } + } + } +*/ + ret[0] = closest; + ret[1] = secondClosest; + return ret; +} +float dither(float color) { + float closestColor = (color < 0.5) ? 0 : 1; + float secondClosestColor = 1 - closestColor; + float d = 1; // -0.5 - fract(ubo.mode.parameters.w / 8.0); + if ( ubo.mode.scalar == 16 ) { + d = indexValue16x16(1); + } else if ( ubo.mode.scalar == 8 ) { + d = indexValue8x8(1); + } else if ( ubo.mode.scalar == 4 ) { + d = indexValue4x4(1); + } + float distance = abs(closestColor - color); + return (distance < d) ? closestColor : secondClosestColor; +} +void dither(inout vec3 color) { + vec3 hsl = rgbToHsl(color); + hsl.x = dither(hsl.x); + color = hslToRgb(hsl); +} +void dither1(inout vec3 color) { + vec3 hsl = rgbToHsl(color); + + float d = 0; + vec3 cs[2] = { hsl, hsl }; // closestColors(hsl.x); + float scale = 1; + if ( ubo.mode.scalar == 16 ) { + d = indexValue16x16(scale); + } else if ( ubo.mode.scalar == 8 ) { + d = indexValue8x8(scale); + } else if ( ubo.mode.scalar == 4 ) { + d = indexValue4x4(scale); + } + float hueDiff = hueDistance(hsl.x, cs[0].x) / hueDistance(cs[1].x, cs[0].x); + float l1 = lightnessStep(max((hsl.z - 0.125), 0.0)); + float l2 = lightnessStep(min((hsl.z + 0.124), 1.0)); + float lightnessDiff = (hsl.z - l1) / (l2 - l1); + + vec3 resultColor = (hueDiff < d) ? cs[0] : cs[1]; + resultColor.z = (lightnessDiff < d) ? l1 : l2; + color = hslToRgb(resultColor); +} + +float rand2(vec2 co){ + return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 143758.5453); +} +float rand3(vec3 co){ + return fract(sin(dot(co.xyz ,vec3(12.9898,78.233, 37.719))) * 143758.5453); +} +void whitenoise(inout vec3 color) { + float flicker = ubo.mode.parameters.x; + float pieces = ubo.mode.parameters.y; + float blend = ubo.mode.parameters.z; + float time = ubo.mode.parameters.w; + if ( blend < 0.0001 ) return; + float freq = sin(pow(mod(time, flicker) + flicker, 1.9)); +// float whiteNoise = rand3( floor(position.world / pieces) + floor(time * 2) ); + float whiteNoise = rand2( floor(gl_FragCoord.xy / pieces) + mod(time, freq) ); + color = mix( color, vec3(whiteNoise), blend ); +} + +void main() { + vec4 albedoSpecular = subpassLoad(samplerAlbedo); + vec3 fragColor = albedoSpecular.rgb * ubo.ambient.rgb; + normal.eye = subpassLoad(samplerNormal).rgb; + position.eye = subpassLoad(samplerPosition).rgb; { + mat4 iView = inverse( ubo.matrices.view[inPushConstantPass] ); + vec4 positionWorld = iView * vec4(position.eye, 1); + position.world = positionWorld.xyz; + } + float litFactor = 1.0; + for ( uint i = 0, shadowMap = 0; i < LIGHTS; ++i ) { + Light light = ubo.lights[i]; + + if ( light.power <= 0.001 ) continue; + + light.position.xyz = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position.xyz, 1)); + if ( light.type > 0 ) { + float shadowFactor = shadowFactor( light, shadowMap++ ); + if ( shadowFactor <= 0.0001 ) continue; + light.power *= shadowFactor; + litFactor += light.power; + } + phong( light, albedoSpecular, fragColor ); + } + + fog(fragColor, litFactor); + + if ( (ubo.mode.type & (0x1 << 0)) == (0x1 << 0) ) { + dither1(fragColor); + } + if ( (ubo.mode.type & (0x1 << 1)) == (0x1 << 1) ) { + whitenoise(fragColor); + } + + outFragColor = vec4(fragColor,1); +} \ No newline at end of file diff --git a/client/client/ext.cpp b/client/client/ext.cpp index b240d0fd..733941c0 100644 --- a/client/client/ext.cpp +++ b/client/client/ext.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include bool client::ready = false; @@ -16,7 +17,7 @@ uf::Serializer client::config; void client::initialize() { uf::IoStream::ncurses = true; - ext::vulkan::device.window = &client::window; + uf::renderer::device.window = &client::window; /* Initialize config */ { struct { uf::Serializer ext; @@ -52,8 +53,8 @@ void client::initialize() { uf::IoStream::ncurses = client::config["window"]["terminal"]["ncurses"].asBool(); // Window's context settings - ext::vulkan::width = size.x; - ext::vulkan::height = size.y; + uf::renderer::settings::width = size.x; + uf::renderer::settings::height = size.y; client::window.create( size, title ); // Miscellaneous @@ -130,10 +131,10 @@ void client::initialize() { client::window.setSize(size); } // Update viewport - ext::vulkan::width = size.x; - ext::vulkan::height = size.y; + uf::renderer::settings::width = size.x; + uf::renderer::settings::height = size.y; - ext::vulkan::resized = true; + uf::renderer::states::resized = true; return "true"; } ); } else if ( client::config["engine"]["hook"]["mode"] == "Both" || client::config["engine"]["hook"]["mode"] == "Optimal" ) { diff --git a/engine/inc/uf/ext/discord/discord.h b/engine/inc/uf/ext/discord/discord.h index 5c34c284..ead47a7a 100644 --- a/engine/inc/uf/ext/discord/discord.h +++ b/engine/inc/uf/ext/discord/discord.h @@ -1,7 +1,6 @@ #pragma once #include -#include namespace ext { namespace discord { diff --git a/engine/inc/uf/ext/vulkan/graphic.h b/engine/inc/uf/ext/vulkan/graphic.h index 679c8863..8b34ccac 100644 --- a/engine/inc/uf/ext/vulkan/graphic.h +++ b/engine/inc/uf/ext/vulkan/graphic.h @@ -9,7 +9,28 @@ namespace ext { namespace vulkan { struct Graphic; + struct GraphicDescriptor { + std::string renderMode = ""; + uint32_t renderTarget = 0; + uint32_t subpass = 0; + uf::BaseGeometry geometry; + size_t indices = 0; + + VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + VkPolygonMode fill = VK_POLYGON_MODE_FILL; + VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT; + float lineWidth = 1.0f; + VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE; + struct { + VkBool32 test = true; + VkBool32 write = true; + VkCompareOp operation = VK_COMPARE_OP_GREATER_OR_EQUAL; + } depthTest; + + std::string hash() const; + bool operator==( const GraphicDescriptor& right ) const { return this->hash() == right.hash(); } + }; struct UF_API Shader : public Buffers { bool aliased = false; @@ -44,7 +65,9 @@ namespace ext { VkDescriptorSet descriptorSet; void initialize( Graphic& graphic ); + void initialize( Graphic& graphic, GraphicDescriptor& descriptor ); void update( Graphic& graphic ); + void update( Graphic& graphic, GraphicDescriptor& descriptor ); void record( Graphic& graphic, VkCommandBuffer ); void destroy(); }; @@ -63,28 +86,7 @@ namespace ext { void initializeShaders( const std::vector>& ); }; struct UF_API Graphic : public Buffers { - struct Descriptor { - std::string renderMode = ""; - uint32_t renderTarget = 0; - uint32_t subpass = 0; - - uf::BaseGeometry geometry; - size_t indices = 0; - - VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - VkPolygonMode fill = VK_POLYGON_MODE_FILL; - VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT; - float lineWidth = 1.0f; - VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE; - struct { - VkBool32 test = true; - VkBool32 write = true; - VkCompareOp operation = VK_COMPARE_OP_GREATER_OR_EQUAL; - } depthTest; - - std::string hash() const; - bool operator==( const Descriptor& right ) const { return this->hash() == right.hash(); } - } descriptor; + GraphicDescriptor descriptor; bool initialized = false; bool process = true; @@ -97,14 +99,15 @@ namespace ext { template void initializeGeometry( uf::BaseMesh& mesh, bool = false ); - bool hasPipeline( Descriptor& descriptor ); + bool hasPipeline( GraphicDescriptor& descriptor ); void initializePipeline(); - Pipeline& initializePipeline( Descriptor& descriptor, bool update = true ); + Pipeline& initializePipeline( GraphicDescriptor& descriptor, bool update = true ); Pipeline& getPipeline(); - Pipeline& getPipeline( Descriptor& descriptor ); + Pipeline& getPipeline( GraphicDescriptor& descriptor ); + void updatePipelines(); void record( VkCommandBuffer commandBuffer ); - void record( VkCommandBuffer commandBuffer, Descriptor& descriptor ); + void record( VkCommandBuffer commandBuffer, GraphicDescriptor& descriptor ); }; } } diff --git a/engine/inc/uf/ext/vulkan/rendermode.h b/engine/inc/uf/ext/vulkan/rendermode.h index 48685e7c..d916253a 100644 --- a/engine/inc/uf/ext/vulkan/rendermode.h +++ b/engine/inc/uf/ext/vulkan/rendermode.h @@ -35,6 +35,7 @@ namespace ext { virtual void initialize( Device& device ); virtual void createCommandBuffers(); virtual void createCommandBuffers( const std::vector& graphics ); + virtual void bindPipelines(); virtual void bindPipelines( const std::vector& graphics ); virtual void tick(); virtual void render(); diff --git a/engine/inc/uf/ext/vulkan/rendermodes/rendertarget.h b/engine/inc/uf/ext/vulkan/rendermodes/rendertarget.h index 693e29b7..1cb45093 100644 --- a/engine/inc/uf/ext/vulkan/rendermodes/rendertarget.h +++ b/engine/inc/uf/ext/vulkan/rendermodes/rendertarget.h @@ -6,10 +6,7 @@ namespace ext { namespace vulkan { struct UF_API RenderTargetRenderMode : public ext::vulkan::RenderMode { - ext::vulkan::Graphic blitter; - - VkFence fence; - VkCommandBuffer commandBuffer; + ext::vulkan::Graphic blitter; std::string target; // RAII diff --git a/engine/inc/uf/ext/vulkan/vulkan.h b/engine/inc/uf/ext/vulkan/vulkan.h index 71f50623..3d5165ca 100644 --- a/engine/inc/uf/ext/vulkan/vulkan.h +++ b/engine/inc/uf/ext/vulkan/vulkan.h @@ -28,40 +28,44 @@ namespace ext { const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData ); - - VkShaderModule loadShader(const char *fileName, VkDevice device); - VkPipelineShaderStageCreateInfo loadShader( std::string fileName, VkShaderStageFlagBits stage, VkDevice device, std::vector& shaderModules ); - uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties); struct VertexDescriptor { VkFormat format; // VK_FORMAT_R32G32B32_SFLOAT std::size_t offset; // offsetof(Vertex, position) }; - - extern UF_API uint32_t width; - extern UF_API uint32_t height; - extern UF_API uint8_t msaa; - - extern UF_API bool validation; - extern UF_API bool rebuildOnTickStart; - extern UF_API bool waitOnRenderEnd; - extern UF_API std::vector validationFilters; - extern UF_API std::vector requestedDeviceFeatures; - extern UF_API std::vector requestedDeviceExtensions; - extern UF_API std::vector requestedInstanceExtensions; - extern UF_API Device device; typedef VmaAllocator Allocator; + + namespace settings { + extern UF_API uint32_t width; + extern UF_API uint32_t height; + extern UF_API uint8_t msaa; + extern UF_API bool validation; + + extern UF_API std::vector validationFilters; + extern UF_API std::vector requestedDeviceFeatures; + extern UF_API std::vector requestedDeviceExtensions; + extern UF_API std::vector requestedInstanceExtensions; + + namespace experimental { + extern UF_API bool rebuildOnTickBegin; + extern UF_API bool waitOnRenderEnd; + extern UF_API bool individualPipelines; + extern UF_API bool multithreadedCommandRecording; + } + } + namespace states { + extern UF_API bool rebuild; + extern UF_API bool resized; + extern UF_API uint32_t currentBuffer; + } + + extern UF_API Device device; extern UF_API Allocator allocator; extern UF_API Swapchain swapchain; extern UF_API std::mutex mutex; - extern UF_API bool rebuild; - extern UF_API bool resized; - extern UF_API uint32_t currentBuffer; - extern UF_API RenderMode* currentRenderMode; - extern UF_API std::vector passes; extern UF_API std::vector renderModes; extern UF_API std::vector scenes; @@ -76,6 +80,7 @@ namespace ext { void UF_API tick(); void UF_API render(); void UF_API destroy(); + void UF_API synchronize( uint8_t = 0b11 ); std::string UF_API allocatorStats(); } } \ No newline at end of file diff --git a/engine/src/engine/object/behavior.cpp b/engine/src/engine/object/behavior.cpp index bd094656..42c5ee98 100644 --- a/engine/src/engine/object/behavior.cpp +++ b/engine/src/engine/object/behavior.cpp @@ -119,7 +119,7 @@ void uf::ObjectBehavior::destroy( uf::Object& self ) { if ( this->hasComponent() ) { auto& graphic = this->getComponent(); graphic.destroy(); - uf::renderer::rebuild = true; + uf::renderer::states::rebuild = true; } } void uf::ObjectBehavior::tick( uf::Object& self ) { diff --git a/engine/src/engine/scene/behavior.cpp b/engine/src/engine/scene/behavior.cpp index f8c1b024..a06b09c9 100644 --- a/engine/src/engine/scene/behavior.cpp +++ b/engine/src/engine/scene/behavior.cpp @@ -7,10 +7,10 @@ UF_BEHAVIOR_ENTITY_CPP_BEGIN(Scene) #define this ((uf::Scene*) &self) void uf::SceneBehavior::initialize( uf::Object& self ) { uf::renderer::scenes.push_back(this); - uf::renderer::rebuild = true; + uf::renderer::states::rebuild = true; this->addHook( "system:Renderer.QueueRebuild", [&](const std::string& event)->std::string{ - uf::renderer::rebuild = true; + uf::renderer::states::rebuild = true; return "true"; }); this->addHook( "system:Destroy", [&](const std::string& event)->std::string{ @@ -34,7 +34,7 @@ void uf::SceneBehavior::render( uf::Object& self ) { void uf::SceneBehavior::destroy( uf::Object& self ) { auto it = std::find(uf::renderer::scenes.begin(), uf::renderer::scenes.end(), this); if ( it != uf::renderer::scenes.end() ) uf::renderer::scenes.erase(it); - uf::renderer::rebuild = true; + uf::renderer::states::rebuild = true; } #undef self UF_BEHAVIOR_ENTITY_CPP_END(Scene) \ No newline at end of file diff --git a/engine/src/ext/discord/achievement_manager.cpp b/engine/src/ext/discord/achievement_manager.cpp index 4b5af3b0..7eeb374a 100644 --- a/engine/src/ext/discord/achievement_manager.cpp +++ b/engine/src/ext/discord/achievement_manager.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -96,3 +97,4 @@ Result AchievementManager::GetUserAchievementAt(std::int32_t index, } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/activity_manager.cpp b/engine/src/ext/discord/activity_manager.cpp index ec0edcff..fcb9b704 100644 --- a/engine/src/ext/discord/activity_manager.cpp +++ b/engine/src/ext/discord/activity_manager.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -175,3 +176,4 @@ void ActivityManager::AcceptInvite(UserId userId, std::function ca } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/application_manager.cpp b/engine/src/ext/discord/application_manager.cpp index 09f9a5a9..f77e7230 100644 --- a/engine/src/ext/discord/application_manager.cpp +++ b/engine/src/ext/discord/application_manager.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -76,3 +77,4 @@ void ApplicationManager::GetTicket(std::function call } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/core.cpp b/engine/src/ext/discord/core.cpp index 7d0160f6..c04e0206 100644 --- a/engine/src/ext/discord/core.cpp +++ b/engine/src/ext/discord/core.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -180,3 +181,4 @@ discord::AchievementManager& Core::AchievementManager() } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/discord.cpp b/engine/src/ext/discord/discord.cpp index ebfba786..7e3e83ff 100644 --- a/engine/src/ext/discord/discord.cpp +++ b/engine/src/ext/discord/discord.cpp @@ -1,4 +1,5 @@ #include +#if defined(UF_USE_DISCORD) #define _CRT_SECURE_NO_WARNINGS #include @@ -437,4 +438,10 @@ void UF_API ext::::discord::initialize() { void UF_API ext::::discord::tick() { DISCORD_REQUIRE(app.core->run_callbacks(app.core)); } -*/ \ No newline at end of file +*/ +#else +void UF_API ext::discord::initialize(){ +} +void UF_API ext::discord::tick(){ +} +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/image_manager.cpp b/engine/src/ext/discord/image_manager.cpp index cf7f6b71..c767f3cb 100644 --- a/engine/src/ext/discord/image_manager.cpp +++ b/engine/src/ext/discord/image_manager.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -55,3 +56,4 @@ Result ImageManager::GetData(ImageHandle handle, std::uint8_t* data, std::uint32 } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/lobby_manager.cpp b/engine/src/ext/discord/lobby_manager.cpp index 85b68496..ca71cc33 100644 --- a/engine/src/ext/discord/lobby_manager.cpp +++ b/engine/src/ext/discord/lobby_manager.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -545,3 +546,4 @@ Result LobbyManager::SendNetworkMessage(LobbyId lobbyId, } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/network_manager.cpp b/engine/src/ext/discord/network_manager.cpp index 2d73d4ec..65b48276 100644 --- a/engine/src/ext/discord/network_manager.cpp +++ b/engine/src/ext/discord/network_manager.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -101,3 +102,4 @@ Result NetworkManager::SendMessage(NetworkPeerId peerId, } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/overlay_manager.cpp b/engine/src/ext/discord/overlay_manager.cpp index 8a2e5205..f585beac 100644 --- a/engine/src/ext/discord/overlay_manager.cpp +++ b/engine/src/ext/discord/overlay_manager.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -110,3 +111,4 @@ void OverlayManager::OpenVoiceSettings(std::function callback) } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/relationship_manager.cpp b/engine/src/ext/discord/relationship_manager.cpp index 789a4130..4e57ab1d 100644 --- a/engine/src/ext/discord/relationship_manager.cpp +++ b/engine/src/ext/discord/relationship_manager.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -88,3 +89,4 @@ Result RelationshipManager::GetAt(std::uint32_t index, Relationship* relationshi } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/storage_manager.cpp b/engine/src/ext/discord/storage_manager.cpp index cf9a7b4c..de04a5f8 100644 --- a/engine/src/ext/discord/storage_manager.cpp +++ b/engine/src/ext/discord/storage_manager.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -156,3 +157,4 @@ Result StorageManager::GetPath(char path[4096]) } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/store_manager.cpp b/engine/src/ext/discord/store_manager.cpp index 31a5367f..5c500f78 100644 --- a/engine/src/ext/discord/store_manager.cpp +++ b/engine/src/ext/discord/store_manager.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -158,3 +159,4 @@ void StoreManager::StartPurchase(Snowflake skuId, std::function ca } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/types.cpp b/engine/src/ext/discord/types.cpp index abe36d36..8dd6f853 100644 --- a/engine/src/ext/discord/types.cpp +++ b/engine/src/ext/discord/types.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -767,3 +768,4 @@ Result LobbySearchQuery::Distance(LobbySearchDistance distance) } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/user_manager.cpp b/engine/src/ext/discord/user_manager.cpp index 2cfc90ef..506d154a 100644 --- a/engine/src/ext/discord/user_manager.cpp +++ b/engine/src/ext/discord/user_manager.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -78,3 +79,4 @@ Result UserManager::CurrentUserHasFlag(UserFlag flag, bool* hasFlag) } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/discord/voice_manager.cpp b/engine/src/ext/discord/voice_manager.cpp index c1d06e45..d642d910 100644 --- a/engine/src/ext/discord/voice_manager.cpp +++ b/engine/src/ext/discord/voice_manager.cpp @@ -1,3 +1,4 @@ +#if defined(UF_USE_DISCORD) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -122,3 +123,4 @@ Result VoiceManager::SetLocalVolume(Snowflake userId, std::uint8_t volume) } } // namespace discord +#endif \ No newline at end of file diff --git a/engine/src/ext/openvr/openvr.cpp b/engine/src/ext/openvr/openvr.cpp index d28ab1b1..9b108423 100644 --- a/engine/src/ext/openvr/openvr.cpp +++ b/engine/src/ext/openvr/openvr.cpp @@ -2,7 +2,7 @@ #include #include #include - +#include #include #include #include @@ -448,8 +448,8 @@ void ext::openvr::submit() { bool invert = swapEyes; ext::vulkan::StereoscopicDeferredRenderMode* renderMode = (ext::vulkan::StereoscopicDeferredRenderMode*) &ext::vulkan::getRenderMode(""); - float width = renderMode->width > 0 ? renderMode->width : ext::vulkan::width; - float height = renderMode->height > 0 ? renderMode->height : ext::vulkan::height; + float width = renderMode->width > 0 ? renderMode->width : uf::renderer::settings::width; + float height = renderMode->height > 0 ? renderMode->height : uf::renderer::settings::height; auto& leftOutputAttachment = renderMode->renderTargets.left.attachments[renderMode->renderTargets.left.attachments.size()-1]; auto& rightOutputAttachment = renderMode->renderTargets.right.attachments[renderMode->renderTargets.right.attachments.size()-1]; diff --git a/engine/src/ext/vulkan/device.cpp b/engine/src/ext/vulkan/device.cpp index cc2ee39c..cc13cf04 100644 --- a/engine/src/ext/vulkan/device.cpp +++ b/engine/src/ext/vulkan/device.cpp @@ -65,11 +65,11 @@ namespace { if ( feature == #NAME ) {\ if ( device.features.NAME == VK_TRUE ) {\ device.enabledFeatures.NAME = true;\ - if ( ext::vulkan::validation ) std::cout << "Enabled feature: " << feature << std::endl;\ - } else if ( ext::vulkan::validation ) std::cout << "Failed to enable feature: " << feature << std::endl;\ + if ( ext::vulkan::settings::validation ) std::cout << "Enabled feature: " << feature << std::endl;\ + } else if ( ext::vulkan::settings::validation ) std::cout << "Failed to enable feature: " << feature << std::endl;\ } - for ( auto& feature : ext::vulkan::requestedDeviceFeatures ) { + for ( auto& feature : ext::vulkan::settings::requestedDeviceFeatures ) { CHECK_FEATURE(robustBufferAccess); CHECK_FEATURE(fullDrawIndexUint32); CHECK_FEATURE(imageCubeArray); @@ -132,8 +132,8 @@ namespace { if ( feature == #NAME ) {\ if ( device.features2.NAME == VK_TRUE ) {\ device.enabledFeatures2.NAME = true;\ - if ( ext::vulkan::validation ) std::cout << "Enabled feature: " << feature << std::endl;\ - } else if ( ext::vulkan::validation ) std::cout << "Failed to enable feature: " << feature << std::endl;\ + if ( ext::vulkan::settings::validation ) std::cout << "Enabled feature: " << feature << std::endl;\ + } else if ( ext::vulkan::settings::validation ) std::cout << "Failed to enable feature: " << feature << std::endl;\ } #undef CHECK_FEATURE2 } @@ -510,7 +510,7 @@ void ext::vulkan::Device::initialize() { "VK_LAYER_KHRONOS_validation" }; // Assert validation layers - if ( ext::vulkan::validation ) { + if ( ext::vulkan::settings::validation ) { uint32_t layerCount; vkEnumerateInstanceLayerProperties(&layerCount, nullptr); std::vector availableLayers(layerCount); @@ -527,14 +527,14 @@ void ext::vulkan::Device::initialize() { } // // Get extensions - std::vector requestedExtensions = window->getExtensions( ext::vulkan::validation ); + std::vector requestedExtensions = window->getExtensions( ext::vulkan::settings::validation ); // Load any requested extensions - requestedExtensions.insert( requestedExtensions.end(), ext::vulkan::requestedInstanceExtensions.begin(), ext::vulkan::requestedInstanceExtensions.end() ); + requestedExtensions.insert( requestedExtensions.end(), ext::vulkan::settings::requestedInstanceExtensions.begin(), ext::vulkan::settings::requestedInstanceExtensions.end() ); // OpenVR Support if ( ext::openvr::enabled ) VRInstanceExtensions(requestedExtensions); { - if ( ext::vulkan::validation ) + if ( ext::vulkan::settings::validation ) for ( auto ext : requestedExtensions ) std::cout << "Requested instance extension: " << ext << std::endl; @@ -551,7 +551,7 @@ void ext::vulkan::Device::initialize() { { std::vector instanceExtensions; for ( auto& s : supportedExtensions.instance ) { - if ( ext::vulkan::validation ) + if ( ext::vulkan::settings::validation ) std::cout << "Enabled instance extension: " << s << std::endl; instanceExtensions.push_back( s.c_str() ); } @@ -571,7 +571,7 @@ void ext::vulkan::Device::initialize() { createInfo.enabledExtensionCount = static_cast(instanceExtensions.size()); createInfo.ppEnabledExtensionNames = instanceExtensions.data(); - if ( ext::vulkan::validation ) { + if ( ext::vulkan::settings::validation ) { createInfo.enabledLayerCount = static_cast(validationLayers.size()); createInfo.ppEnabledLayerNames = validationLayers.data(); } else { @@ -581,7 +581,7 @@ void ext::vulkan::Device::initialize() { VK_CHECK_RESULT( vkCreateInstance( &createInfo, nullptr, &this->instance )); } // Setup debug - if ( ext::vulkan::validation ) { + if ( ext::vulkan::settings::validation ) { VkDebugUtilsMessengerCreateInfoEXT createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; @@ -649,7 +649,7 @@ void ext::vulkan::Device::initialize() { else if (counts & VK_SAMPLE_COUNT_8_BIT) maxSamples = 8; else if (counts & VK_SAMPLE_COUNT_4_BIT) maxSamples = 4; else if (counts & VK_SAMPLE_COUNT_2_BIT) maxSamples = 2; - ext::vulkan::msaa = std::min( maxSamples, ext::vulkan::msaa ); + ext::vulkan::settings::msaa = std::min( maxSamples, ext::vulkan::settings::msaa ); } } // Create logical device @@ -657,14 +657,14 @@ void ext::vulkan::Device::initialize() { bool useSwapChain = true; VkQueueFlags requestedQueueTypes = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT; std::vector requestedExtensions; - requestedExtensions.insert( requestedExtensions.end(), ext::vulkan::requestedDeviceExtensions.begin(), ext::vulkan::requestedDeviceExtensions.end() ); + requestedExtensions.insert( requestedExtensions.end(), ext::vulkan::settings::requestedDeviceExtensions.begin(), ext::vulkan::settings::requestedDeviceExtensions.end() ); // OpenVR Support if ( ext::openvr::enabled ) { VRDeviceExtensions( this->physicalDevice, requestedExtensions); } { // Allocate enough ExtensionProperties to support all extensions being enabled - if ( ext::vulkan::validation ) + if ( ext::vulkan::settings::validation ) for ( auto ext : requestedExtensions ) std::cout << "Requested device extension: " << ext << std::endl; uint32_t extensionsCount = 0; @@ -680,7 +680,7 @@ void ext::vulkan::Device::initialize() { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; for ( auto& s : supportedExtensions.device ) { - if ( ext::vulkan::validation ) std::cout << "Enabled device extension: " << s << std::endl; + if ( ext::vulkan::settings::validation ) std::cout << "Enabled device extension: " << s << std::endl; deviceExtensions.push_back( s.c_str() ); } @@ -758,7 +758,7 @@ void ext::vulkan::Device::initialize() { if ( vkCreateDevice( this->physicalDevice, &deviceCreateInfo, nullptr, &this->logicalDevice) != VK_SUCCESS ) throw std::runtime_error("failed to create logical device!"); - if ( ext::vulkan::validation ) + if ( ext::vulkan::settings::validation ) std::cout << retrieveDeviceFeatures( *this ) << std::endl; } // Create command pool diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index 17884262..c25841ce 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -214,14 +214,17 @@ void ext::vulkan::Shader::destroy() { } void ext::vulkan::Pipeline::initialize( Graphic& graphic ) { + return this->initialize( graphic, graphic.descriptor ); +} +void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& descriptor ) { this->device = graphic.device; Device& device = *graphic.device; // std::cout << &graphic << ": Shaders: " << graphic.material.shaders.size() << " Textures: " << graphic.material.textures.size() << std::endl; assert( graphic.material.shaders.size() > 0 ); - RenderMode& renderMode = ext::vulkan::getRenderMode(graphic.descriptor.renderMode, true); - auto& renderTarget = renderMode.getRenderTarget( graphic.descriptor.renderTarget ); + RenderMode& renderMode = ext::vulkan::getRenderMode( descriptor.renderMode, true); + auto& renderTarget = renderMode.getRenderTarget( descriptor.renderTarget ); { std::vector descriptorSetLayoutBindings; std::vector pushConstantRanges; @@ -302,14 +305,14 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic ) { // Graphic { VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = ext::vulkan::initializers::pipelineInputAssemblyStateCreateInfo( - graphic.descriptor.topology, + descriptor.topology, 0, VK_FALSE ); VkPipelineRasterizationStateCreateInfo rasterizationState = ext::vulkan::initializers::pipelineRasterizationStateCreateInfo( - graphic.descriptor.fill, - graphic.descriptor.cullMode, // VK_CULL_MODE_NONE, - graphic.descriptor.frontFace, + descriptor.fill, + descriptor.cullMode, // VK_CULL_MODE_NONE, + descriptor.frontFace, 0 ); rasterizationState.lineWidth = graphic.descriptor.lineWidth; @@ -317,7 +320,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic ) { std::vector blendAttachmentStates; if ( renderMode.getType() != "Swapchain" ) { - auto& subpass = renderTarget.passes[graphic.descriptor.subpass]; + auto& subpass = renderTarget.passes[descriptor.subpass]; for ( auto& color : subpass.colors ) { blendAttachmentStates.push_back(renderTarget.attachments[color.attachment].blendState); } @@ -328,7 +331,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic ) { } } } else { - graphic.descriptor.subpass = 0; + descriptor.subpass = 0; VkBool32 blendEnabled = VK_FALSE; VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT; @@ -358,15 +361,15 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic ) { blendAttachmentStates.data() ); VkPipelineDepthStencilStateCreateInfo depthStencilState = ext::vulkan::initializers::pipelineDepthStencilStateCreateInfo( - graphic.descriptor.depthTest.test, - graphic.descriptor.depthTest.write, - graphic.descriptor.depthTest.operation //VK_COMPARE_OP_LESS_OR_EQUAL + descriptor.depthTest.test, + descriptor.depthTest.write, + descriptor.depthTest.operation //VK_COMPARE_OP_LESS_OR_EQUAL ); VkPipelineViewportStateCreateInfo viewportState = ext::vulkan::initializers::pipelineViewportStateCreateInfo( 1, 1, 0 ); VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; - switch ( ext::vulkan::msaa ) { + switch ( ext::vulkan::settings::msaa ) { case 64: samples = VK_SAMPLE_COUNT_64_BIT; break; case 32: samples = VK_SAMPLE_COUNT_32_BIT; break; case 16: samples = VK_SAMPLE_COUNT_16_BIT; break; @@ -393,14 +396,14 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic ) { std::vector vertexBindingDescriptions = { ext::vulkan::initializers::vertexInputBindingDescription( VERTEX_BUFFER_BIND_ID, - graphic.descriptor.geometry.sizes.vertex, + descriptor.geometry.sizes.vertex, VK_VERTEX_INPUT_RATE_VERTEX ) }; // Attribute descriptions // Describes memory layout and shader positions std::vector vertexAttributeDescriptions = {}; - for ( auto& attribute : graphic.descriptor.geometry.attributes ) { + for ( auto& attribute : descriptor.geometry.attributes ) { auto d = ext::vulkan::initializers::vertexInputAttributeDescription( VERTEX_BUFFER_BIND_ID, vertexAttributeDescriptions.size(), @@ -436,7 +439,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic ) { pipelineCreateInfo.pDynamicState = &dynamicState; pipelineCreateInfo.stageCount = shaderDescriptors.size(); pipelineCreateInfo.pStages = shaderDescriptors.data(); - pipelineCreateInfo.subpass = graphic.descriptor.subpass; + pipelineCreateInfo.subpass = descriptor.subpass; VK_CHECK_RESULT(vkCreateGraphicsPipelines( device, device.pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); } @@ -476,11 +479,14 @@ void ext::vulkan::Pipeline::record( Graphic& graphic, VkCommandBuffer commandBuf vkCmdBindPipeline(commandBuffer, bindPoint, pipeline); } void ext::vulkan::Pipeline::update( Graphic& graphic ) { + return this->update( graphic, graphic.descriptor ); +} +void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descriptor ) { // generate fallback empty texture auto& emptyTexture = Texture2D::empty; - RenderMode& renderMode = ext::vulkan::getRenderMode(graphic.descriptor.renderMode, true); - auto& renderTarget = renderMode.getRenderTarget(graphic.descriptor.renderTarget ); + RenderMode& renderMode = ext::vulkan::getRenderMode(descriptor.renderMode, true); + auto& renderTarget = renderMode.getRenderTarget(descriptor.renderTarget ); std::vector writeDescriptorSets; std::vector descriptorSetLayoutBindings; @@ -491,8 +497,8 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) { descriptorSetLayoutBindings.insert( descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.end() ); } - if ( graphic.descriptor.subpass < renderTarget.passes.size() ) { - auto& subpass = renderTarget.passes[graphic.descriptor.subpass]; + if ( descriptor.subpass < renderTarget.passes.size() ) { + auto& subpass = renderTarget.passes[descriptor.subpass]; for ( auto& input : subpass.inputs ) { inputDescriptors.push_back(ext::vulkan::initializers::descriptorImageInfo( renderTarget.attachments[input.attachment].view, @@ -525,14 +531,14 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) { if ( buffer.usageFlags & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT ) { auto& descriptor = buffersStorageVector.emplace_back(buffer.descriptor); if ( descriptor.offset % device->properties.limits.minStorageBufferOffsetAlignment != 0 ) { - std::cout << __LINE__ << ": Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.offset << std::endl; + std::cout << "[" << __LINE__ << "] Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.offset << std::endl; descriptor.offset = 0; } } if ( buffer.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ) { auto& descriptor = buffersUniformsVector.emplace_back(buffer.descriptor); if ( descriptor.offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) { - std::cout << __LINE__ << ": Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.offset << std::endl; + std::cout << "[" << __LINE__ << "] Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.offset << std::endl; descriptor.offset = 0; } } @@ -673,7 +679,7 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) { for ( size_t i = 0; i < descriptor.descriptorCount; ++i ) { if ( descriptor.pBufferInfo[i].offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) { // std::cout << "Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.pBufferInfo[i].offset << std::endl; - std::cout << "Invalid descriptor for buffer: " << descriptor.pBufferInfo[i].buffer << " " << descriptor.pBufferInfo[i].offset << " " << descriptor.pBufferInfo[i].range << ", invalidating..." << std::endl; + std::cout << "[" << __LINE__ << "] Invalid descriptor for buffer: " << descriptor.pBufferInfo[i].buffer << " " << descriptor.pBufferInfo[i].offset << " " << descriptor.pBufferInfo[i].range << ", invalidating..." << std::endl; auto pointer = const_cast(&descriptor.pBufferInfo[i]); pointer->offset = 0; pointer->range = 0; @@ -774,33 +780,38 @@ void ext::vulkan::Graphic::initialize( const std::string& renderModeName ) { void ext::vulkan::Graphic::initializePipeline() { initializePipeline( this->descriptor, false ); } -ext::vulkan::Pipeline& ext::vulkan::Graphic::initializePipeline( Descriptor& descriptor, bool update ) { +ext::vulkan::Pipeline& ext::vulkan::Graphic::initializePipeline( GraphicDescriptor& descriptor, bool update ) { auto& pipeline = pipelines[descriptor.hash()]; - Descriptor previous = this->descriptor; - this->descriptor = descriptor; - pipeline.initialize(*this); - pipeline.update(*this); - if ( !update ) this->descriptor = previous; +// auto previous = this->descriptor; +// this->descriptor = descriptor; + pipeline.initialize(*this, descriptor); + pipeline.update(*this, descriptor); +// if ( !update ) this->descriptor = previous; initialized = true; return pipeline; } -bool ext::vulkan::Graphic::hasPipeline( Descriptor& descriptor ) { +bool ext::vulkan::Graphic::hasPipeline( GraphicDescriptor& descriptor ) { return pipelines.count( descriptor.hash() ) > 0; } ext::vulkan::Pipeline& ext::vulkan::Graphic::getPipeline() { return getPipeline( descriptor ); } -ext::vulkan::Pipeline& ext::vulkan::Graphic::getPipeline( Descriptor& descriptor ) { +ext::vulkan::Pipeline& ext::vulkan::Graphic::getPipeline( GraphicDescriptor& descriptor ) { if ( !hasPipeline(descriptor) ) return initializePipeline( descriptor ); return pipelines[descriptor.hash()]; } +void ext::vulkan::Graphic::updatePipelines() { + for ( auto pair : this->pipelines ) { + pair.second.update( *this ); + } +} void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer ) { return this->record( commandBuffer, descriptor ); } -void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, Descriptor& descriptor ) { +void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, GraphicDescriptor& descriptor ) { if ( !this->hasPipeline( descriptor ) ) { std::cout << this << ": has no valid pipeline" << std::endl; return; @@ -838,14 +849,15 @@ void ext::vulkan::Graphic::destroy() { ext::vulkan::Buffers::destroy(); - ext::vulkan::rebuild = true; + ext::vulkan::states::rebuild = true; } #include -std::string ext::vulkan::Graphic::Descriptor::hash() const { +std::string ext::vulkan::GraphicDescriptor::hash() const { uf::Serializer serializer; serializer["subpass"] = subpass; + if ( settings::experimental::individualPipelines ) serializer["renderMode"] = renderMode; serializer["renderTarget"] = renderTarget; serializer["geometry"]["sizes"]["vertex"] = geometry.sizes.vertex; serializer["geometry"]["sizes"]["indices"] = geometry.sizes.indices; @@ -867,6 +879,6 @@ std::string ext::vulkan::Graphic::Descriptor::hash() const { serializer["depthTest"]["write"] = depthTest.write; serializer["depthTest"]["operation"] = depthTest.operation; -// std::cout << this << ": " << indices << ": " << renderMode << ": " << subpass << ": " << serializer << std::endl; +// if ( renderMode != "Gui" ) std::cout << this << ": " << indices << ": " << renderMode << ": " << subpass << ": " << serializer << std::endl; return uf::string::sha256( serializer.serialize() ); } \ No newline at end of file diff --git a/engine/src/ext/vulkan/rendermode.cpp b/engine/src/ext/vulkan/rendermode.cpp index 615c0d71..e96a9a0c 100644 --- a/engine/src/ext/vulkan/rendermode.cpp +++ b/engine/src/ext/vulkan/rendermode.cpp @@ -34,16 +34,7 @@ void ext::vulkan::RenderMode::createCommandBuffers() { std::function filter = [&]( uf::Entity* entity ) { if ( !entity->hasComponent() ) return; ext::vulkan::Graphic& graphic = entity->getComponent(); - if ( !graphic.initialized ) return; - if ( !graphic.process ) return; - /* - if ( !entity->hasComponent() ) return; - uf::MeshBase& mesh = entity->getComponent(); - if ( !mesh.generated ) return; - ext::vulkan::Graphic& graphic = mesh.graphic; - if ( !graphic.initialized ) return; - if ( !graphic.process ) return; - */ + if ( !graphic.initialized || !graphic.process ) return; graphics.push_back(&graphic); }; for ( uf::Scene* scene : ext::vulkan::scenes ) { @@ -52,7 +43,7 @@ void ext::vulkan::RenderMode::createCommandBuffers() { } this->synchronize(); - bindPipelines( graphics ); +// bindPipelines( graphics ); createCommandBuffers( graphics ); this->mostRecentCommandPoolId = std::this_thread::get_id(); this->rebuild = false; @@ -75,45 +66,35 @@ ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getComma VK_CHECK_RESULT(vkAllocateCommandBuffers(*device, &cmdBufAllocateInfo, commands.data())); } return commands; -/* - VkCommandPool* pool = NULL; - switch ( queueEnum ) { - case QueueEnum::GRAPHICS: - index = device.queueFamilyIndices.graphics; - if ( commandPool.graphics.count(id) > 0 ) exists = true; - pool = &commandPool.graphics[id]; - break; - case QueueEnum::COMPUTE: - index = device.queueFamilyIndices.compute; - if ( commandPool.compute.count(id) > 0 ) exists = true; - pool = &commandPool.compute[id]; - break; - case QueueEnum::TRANSFER: - index = device.queueFamilyIndices.transfer; - if ( commandPool.transfer.count(id) > 0 ) exists = true; - pool = &commandPool.transfer[id]; - break; - } - if ( !exists ) { - VkCommandPoolCreateFlags createFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VkCommandPoolCreateInfo cmdPoolInfo = {}; - cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmdPoolInfo.queueFamilyIndex = index; - cmdPoolInfo.flags = createFlags; - if ( vkCreateCommandPool( this->logicalDevice, &cmdPoolInfo, nullptr, pool ) != VK_SUCCESS ) - throw std::runtime_error("failed to create command pool for graphics!"); - } - return *pool; -*/ } void ext::vulkan::RenderMode::createCommandBuffers( const std::vector& graphics ) { +} +void ext::vulkan::RenderMode::bindPipelines() { + this->execute = true; + + std::vector graphics; + std::function filter = [&]( uf::Entity* entity ) { + if ( !entity->hasComponent() ) return; + ext::vulkan::Graphic& graphic = entity->getComponent(); + if ( !graphic.initialized ) return; + if ( !graphic.process ) return; + graphics.push_back(&graphic); + }; + for ( uf::Scene* scene : ext::vulkan::scenes ) { + if ( !scene ) continue; + scene->process(filter); + } + + this->synchronize(); + this->bindPipelines( graphics ); } void ext::vulkan::RenderMode::bindPipelines( const std::vector& graphics ) { for ( auto* pointer : graphics ) { auto& graphic = *pointer; // copy descriptor - ext::vulkan::Graphic::Descriptor descriptor = graphic.descriptor; + if ( graphic.descriptor.renderMode == this->getName() ) continue; + ext::vulkan::GraphicDescriptor descriptor = graphic.descriptor; // bind to this render mode descriptor.renderMode = this->getName(); // ignore if pipeline exists for this render mode @@ -125,11 +106,11 @@ void ext::vulkan::RenderMode::bindPipelines( const std::vectormostRecentCommandPoolId ); // Get next image in the swap chain (back/front buffer) - VK_CHECK_RESULT(swapchain.acquireNextImage(¤tBuffer, swapchain.presentCompleteSemaphore)); + VK_CHECK_RESULT(swapchain.acquireNextImage(&states::currentBuffer, swapchain.presentCompleteSemaphore)); // Use a fence to wait until the command buffer has finished execution before using it again - VK_CHECK_RESULT(vkWaitForFences(*device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX)); - VK_CHECK_RESULT(vkResetFences(*device, 1, &fences[currentBuffer])); + VK_CHECK_RESULT(vkWaitForFences(*device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX)); + VK_CHECK_RESULT(vkResetFences(*device, 1, &fences[states::currentBuffer])); // Pipeline stage at which the queue submission will wait (via pWaitSemaphores) VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; @@ -141,17 +122,17 @@ void ext::vulkan::RenderMode::render() { submitInfo.waitSemaphoreCount = 1; // One wait semaphore submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed submitInfo.signalSemaphoreCount = 1; // One signal semaphore - submitInfo.pCommandBuffers = &commands[currentBuffer]; // Command buffers(s) to execute in this batch (submission) + submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission) submitInfo.commandBufferCount = 1; // Submit to the graphics queue passing a wait fence - VK_CHECK_RESULT(vkQueueSubmit( device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[currentBuffer])); - //vkQueueSubmit(device->queues.graphics, 1, &submitInfo, fences[currentBuffer]); + VK_CHECK_RESULT(vkQueueSubmit( device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer])); + //vkQueueSubmit(device->queues.graphics, 1, &submitInfo, fences[states::currentBuffer]); // Present the current buffer to the swap chain // Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation // This ensures that the image is not presented to the windowing system until all commands have been submitted - VK_CHECK_RESULT(swapchain.queuePresent(device->getQueue( Device::QueueEnum::PRESENT ), currentBuffer, renderCompleteSemaphore)); + VK_CHECK_RESULT(swapchain.queuePresent(device->getQueue( Device::QueueEnum::PRESENT ), states::currentBuffer, renderCompleteSemaphore)); VK_CHECK_RESULT(vkQueueWaitIdle(device->getQueue( Device::QueueEnum::PRESENT ))); } diff --git a/engine/src/ext/vulkan/rendermodes/base.cpp b/engine/src/ext/vulkan/rendermodes/base.cpp index f23cbdca..57867b37 100644 --- a/engine/src/ext/vulkan/rendermodes/base.cpp +++ b/engine/src/ext/vulkan/rendermodes/base.cpp @@ -21,8 +21,8 @@ std::string ext::vulkan::BaseRenderMode::getType() const { void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vector& graphics ) { if ( ext::vulkan::renderModes.size() > 1 ) return; - float width = this->width > 0 ? this->width : ext::vulkan::width; - float height = this->height > 0 ? this->height : ext::vulkan::height; + float width = this->width > 0 ? this->width : ext::vulkan::settings::width; + float height = this->height > 0 ? this->height : ext::vulkan::settings::height; VkCommandBufferBeginInfo commandBufferInfo = {}; commandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -83,7 +83,7 @@ void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vectordestroy(); this->initialize( *this->device ); } @@ -110,8 +110,8 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) { renderTarget.attachments.clear(); renderTarget.attachments.resize( ext::vulkan::swapchain.buffers + 1 ); - uint32_t width = this->width > 0 ? this->width : ext::vulkan::width; - uint32_t height = this->height > 0 ? this->height : ext::vulkan::height; + uint32_t width = this->width > 0 ? this->width : ext::vulkan::settings::width; + uint32_t height = this->height > 0 ? this->height : ext::vulkan::settings::height; for ( size_t i = 0; i < images.size(); ++i ) { VkImageViewCreateInfo colorAttachmentView = {}; diff --git a/engine/src/ext/vulkan/rendermodes/compute.cpp b/engine/src/ext/vulkan/rendermodes/compute.cpp index a5696844..6d827b8f 100644 --- a/engine/src/ext/vulkan/rendermodes/compute.cpp +++ b/engine/src/ext/vulkan/rendermodes/compute.cpp @@ -24,8 +24,8 @@ void ext::vulkan::ComputeRenderMode::initialize( Device& device ) { // this->height = 2160; { - auto width = this->width > 0 ? this->width : ext::vulkan::width; - auto height = this->height > 0 ? this->height : ext::vulkan::height; + auto width = this->width > 0 ? this->width : ext::vulkan::settings::width; + auto height = this->height > 0 ? this->height : ext::vulkan::settings::height; compute.device = &device; compute.material.device = &device; @@ -61,8 +61,8 @@ void ext::vulkan::ComputeRenderMode::initialize( Device& device ) { // update buffers if ( !compute.buffers.empty() ) { - auto& pipeline = compute.getPipeline(); - pipeline.update( compute ); + // compute.getPipeline().update( compute ); + compute.updatePipelines(); } } { @@ -102,24 +102,24 @@ void ext::vulkan::ComputeRenderMode::render() { auto& commands = getCommands( this->mostRecentCommandPoolId ); // Submit compute commands // Use a fence to ensure that compute command buffer has finished executing before using it again - VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX )); - VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[currentBuffer] )); + VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX )); + VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[states::currentBuffer] )); VkSubmitInfo submitInfo = ext::vulkan::initializers::submitInfo(); submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &commands[currentBuffer]; + submitInfo.pCommandBuffers = &commands[states::currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( Device::QueueEnum::COMPUTE ), 1, &submitInfo, fences[currentBuffer])); - //vkQueueSubmit(device->queues.compute, 1, &submitInfo, fences[currentBuffer]); + VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( Device::QueueEnum::COMPUTE ), 1, &submitInfo, fences[states::currentBuffer])); + //vkQueueSubmit(device->queues.compute, 1, &submitInfo, fences[states::currentBuffer]); } void ext::vulkan::ComputeRenderMode::tick() { ext::vulkan::RenderMode::tick(); - if ( ext::vulkan::resized ) { + if ( ext::vulkan::states::resized ) { // auto-resize texture if ( this->width == 0 && this->height == 0 ) { - auto width = this->width > 0 ? this->width : ext::vulkan::width; - auto height = this->height > 0 ? this->height : ext::vulkan::height; + auto width = this->width > 0 ? this->width : ext::vulkan::settings::width; + auto height = this->height > 0 ? this->height : ext::vulkan::settings::height; for ( auto& texture : compute.material.textures ) { texture.destroy(); } @@ -138,9 +138,11 @@ void ext::vulkan::ComputeRenderMode::tick() { texture.device = NULL; } blitter.getPipeline().update( blitter ); + // blitter.updatePipelines(); } if ( !compute.buffers.empty() ) { compute.getPipeline().update( compute ); + // compute.updatePipelines(); } } } @@ -200,8 +202,8 @@ void ext::vulkan::ComputeRenderMode::pipelineBarrier( VkCommandBuffer commandBuf void ext::vulkan::ComputeRenderMode::createCommandBuffers( ) { this->synchronize(); - float width = this->width > 0 ? this->width : ext::vulkan::width; - float height = this->height > 0 ? this->height : ext::vulkan::height; + float width = this->width > 0 ? this->width : ext::vulkan::settings::width; + float height = this->height > 0 ? this->height : ext::vulkan::settings::height; VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo(); auto& pipeline = compute.getPipeline(); diff --git a/engine/src/ext/vulkan/rendermodes/deferred.cpp b/engine/src/ext/vulkan/rendermodes/deferred.cpp index 55778b8c..ff866ddc 100644 --- a/engine/src/ext/vulkan/rendermodes/deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/deferred.cpp @@ -72,7 +72,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { renderTarget.addPass( VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, { attachments.output }, - { attachments.albedo, attachments.normals, attachments.position/*, attachments.depth*/ }, + { attachments.albedo, attachments.normals, attachments.position }, attachments.depth ); } @@ -98,7 +98,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { blitter.initializeGeometry( mesh ); blitter.material.initializeShaders({ {"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT}, - {"./data/shaders/display.subpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT} + {"./data/shaders/display.subpass.stereo.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT} }); { auto& scene = uf::scene::getCurrentScene(); @@ -156,11 +156,12 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { void ext::vulkan::DeferredRenderMode::tick() { ext::vulkan::RenderMode::tick(); - if ( ext::vulkan::resized ) { + if ( ext::vulkan::states::resized ) { renderTarget.initialize( *renderTarget.device ); // update blitter descriptor set if ( blitter.initialized ) { blitter.getPipeline().update( blitter ); + // blitter.updatePipelines(); } } } @@ -169,24 +170,12 @@ void ext::vulkan::DeferredRenderMode::destroy() { blitter.destroy(); } void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector& graphics ) { - // destroy if exists - // ext::vulkan::RenderMode& swapchain = - float width = this->width > 0 ? this->width : ext::vulkan::width; - float height = this->height > 0 ? this->height : ext::vulkan::height; + float width = this->width > 0 ? this->width : ext::vulkan::settings::width; + float height = this->height > 0 ? this->height : ext::vulkan::settings::height; VkCommandBufferBeginInfo cmdBufInfo = {}; cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; cmdBufInfo.pNext = nullptr; -/* - VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; - imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED - imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED - imageMemoryBarrier.subresourceRange.baseMipLevel = 0; - imageMemoryBarrier.subresourceRange.levelCount = 1; - imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; - imageMemoryBarrier.subresourceRange.layerCount = 1; - imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; -*/ std::vector layers = ext::vulkan::getRenderModes(std::vector{"RenderTarget", "Compute"}, false); auto& scene = uf::scene::getCurrentScene(); @@ -246,21 +235,6 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vectorpipelineBarrier( commands[i], 0 ); - /* - if ( layer->getName() == "" ) continue; - RenderTarget& renderTarget = layer->renderTarget; - for ( auto& attachment : renderTarget.attachments ) { - if ( !(attachment.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue; - if ( (attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; - imageMemoryBarrier.image = attachment.image; - imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT; - imageMemoryBarrier.oldLayout = attachment.layout; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT , VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); - attachment.layout = imageMemoryBarrier.newLayout; - } - */ } vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); @@ -269,15 +243,14 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vectordescriptor.renderMode != this->getName() ) continue; - graphic->record(commands[i] ); + graphic->record( commands[i] ); } - // render gui layer + // blit any RT's { for ( auto _ : layers ) { RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _; auto& blitter = layer->blitter; - if ( !blitter.initialized ) continue; - if ( blitter.descriptor.subpass != 0 ) continue; + if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != 0 ) continue; blitter.record(commands[i]); } } @@ -285,13 +258,12 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vectorblitter; - if ( !blitter.initialized ) continue; - if ( blitter.descriptor.subpass != 1 ) continue; + if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != 1 ) continue; blitter.record(commands[i]); } } @@ -299,21 +271,6 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vectorpipelineBarrier( commands[i], 1 ); - /* - if ( layer->getName() == "" ) continue; - RenderTarget& renderTarget = layer->renderTarget; - for ( auto& attachment : renderTarget.attachments ) { - if ( !(attachment.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue; - if ( (attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; - imageMemoryBarrier.image = attachment.image; - imageMemoryBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imageMemoryBarrier.oldLayout = attachment.layout; - imageMemoryBarrier.newLayout = attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT , 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); - attachment.layout = imageMemoryBarrier.newLayout; - } - */ } } diff --git a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp index aef37379..703c5db4 100644 --- a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp @@ -67,7 +67,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { ); } // NOP - { + if ( !false ) { renderTarget.addPass( VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, { attachments.output }, @@ -78,7 +78,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { } renderTarget.initialize( device ); - { + if ( blitter.process ) { uf::BaseMesh mesh; mesh.vertices = { { {-1.0f, 1.0f}, {0.0f, 1.0f}, }, @@ -108,19 +108,18 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { } void ext::vulkan::RenderTargetRenderMode::tick() { ext::vulkan::RenderMode::tick(); - if ( ext::vulkan::resized ) { + if ( ext::vulkan::states::resized ) { renderTarget.initialize( *renderTarget.device ); - blitter.material.textures.clear(); for ( auto& attachment : renderTarget.attachments ) { if ( !(attachment.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue; - Texture2D& texture = blitter.material.textures.emplace_back(); texture.aliasAttachment(attachment); } - - auto& pipeline = blitter.getPipeline(); - pipeline.update( blitter ); + if ( blitter.process ) { + blitter.getPipeline().update( blitter ); + // blitter.updatePipelines(); + } } } void ext::vulkan::RenderTargetRenderMode::destroy() { @@ -131,8 +130,8 @@ void ext::vulkan::RenderTargetRenderMode::render() { auto& commands = getCommands( this->mostRecentCommandPoolId ); // Submit commands // Use a fence to ensure that command buffer has finished executing before using it again - VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX )); - VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[currentBuffer] )); + VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX )); + VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[states::currentBuffer] )); // Pipeline stage at which the queue submission will wait (via pWaitSemaphores) VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; @@ -146,11 +145,11 @@ void ext::vulkan::RenderTargetRenderMode::render() { submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed submitInfo.signalSemaphoreCount = 1; // One signal semaphore */ - submitInfo.pCommandBuffers = &commands[currentBuffer]; // Command buffers(s) to execute in this batch (submission) + submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission) submitInfo.commandBufferCount = 1; - VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[currentBuffer])); - //vkQueueSubmit(device->queues.graphics, 1, &submitInfo, fences[currentBuffer]); + VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer])); + //vkQueueSubmit(device->queues.graphics, 1, &submitInfo, fences[states::currentBuffer]); /* VkSemaphoreWaitInfo waitInfo = {}; waitInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO; @@ -217,8 +216,8 @@ void ext::vulkan::RenderTargetRenderMode::pipelineBarrier( VkCommandBuffer comma } void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vector& graphics ) { // destroy if exists - float width = this->width > 0 ? this->width : ext::vulkan::width; - float height = this->height > 0 ? this->height : ext::vulkan::height; + float width = this->width > 0 ? this->width : ext::vulkan::settings::width; + float height = this->height > 0 ? this->height : ext::vulkan::settings::height; VkCommandBufferBeginInfo cmdBufInfo = {}; cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -269,11 +268,11 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto vkCmdSetScissor(commands[i], 0, 1, &scissor); for ( auto graphic : graphics ) { if ( graphic->descriptor.renderMode != this->target ) continue; - ext::vulkan::Graphic::Descriptor descriptor = graphic->descriptor; - descriptor.renderMode = this->name; + ext::vulkan::GraphicDescriptor descriptor = graphic->descriptor; + // descriptor.renderMode = this->name; graphic->record(commands[i], descriptor ); } - vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); + if ( !false ) vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); vkCmdEndRenderPass(commands[i]); } diff --git a/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp b/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp index a44555a3..1f2185f6 100644 --- a/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp @@ -85,14 +85,29 @@ void ext::vulkan::StereoscopicDeferredRenderMode::initialize( Device& device ) { ); } // Second pass: write to output - { + /* + if ( i == 0 ) { renderTarget.addPass( VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, { attachments.output }, - { attachments.albedo, attachments.normals, attachments.position/*, attachments.depth*/ }, + { attachments.albedo, attachments.normals, attachments.depth }, + attachments.depth + ); + } else { + renderTarget.addPass( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + { attachments.output }, + { attachments.albedo, attachments.normals, attachments.position }, attachments.depth ); } + */ + renderTarget.addPass( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + { attachments.output }, + { attachments.albedo, attachments.normals, attachments.position }, + attachments.depth + ); renderTarget.initialize( device ); { uf::BaseMesh mesh; @@ -112,10 +127,18 @@ void ext::vulkan::StereoscopicDeferredRenderMode::initialize( Device& device ) { blitter.initialize( this->getName() ); blitter.initializeGeometry( mesh ); - blitter.material.initializeShaders({ - {"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT}, - {"./data/shaders/display.subpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT} - }); + if ( i == 0 ) { + blitter.material.initializeShaders({ + {"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT}, + // {"./data/shaders/display.subpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT} + {"./data/shaders/display.subpass.stereo.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT} + }); + } else { + blitter.material.initializeShaders({ + {"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT}, + {"./data/shaders/display.subpass.stereo.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT} + }); + } { auto& scene = uf::scene::getCurrentScene(); auto& metadata = scene.getComponent(); @@ -141,11 +164,12 @@ void ext::vulkan::StereoscopicDeferredRenderMode::initialize( Device& device ) { } blitter.initializePipeline(); } + ++i; } } void ext::vulkan::StereoscopicDeferredRenderMode::tick() { ext::vulkan::RenderMode::tick(); - if ( ext::vulkan::resized ) { + if ( ext::vulkan::states::resized ) { struct EYES { RenderTarget* renderTarget; Graphic* blitter; @@ -160,8 +184,8 @@ void ext::vulkan::StereoscopicDeferredRenderMode::tick() { renderTarget.initialize( *renderTarget.device ); if ( blitter.initialized ) { - auto& pipeline = blitter.getPipeline(); - pipeline.update( blitter ); + blitter.getPipeline().update( blitter ); + // blitter.updatePipelines(); } } } @@ -176,8 +200,8 @@ void ext::vulkan::StereoscopicDeferredRenderMode::destroy() { void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const std::vector& graphics ) { // destroy if exists // ext::vulkan::RenderMode& swapchain = - float width = this->width > 0 ? this->width : ext::vulkan::width; - float height = this->height > 0 ? this->height : ext::vulkan::height; + float width = this->width > 0 ? this->width : ext::vulkan::settings::width; + float height = this->height > 0 ? this->height : ext::vulkan::settings::height; VkCommandBufferBeginInfo cmdBufInfo = {}; cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -270,20 +294,6 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st for ( auto graphic : graphics ) { // only draw graphics that are assigned to this type of render mode if ( graphic->descriptor.renderMode != this->getName() ) continue; - // update push constants - /* - auto& shaders = graphic->material.shaders; - for ( auto& shader : shaders ) { - for ( auto& pushConstant : shader.pushConstants ) { - struct Stereo { - uint32_t pass; - }; - auto& stereo = pushConstant.get(); - stereo.pass = ext::openvr::renderPass; - std::cout << pushConstant.data().data << ": Expecting " << stereo.pass << std::endl; - } - } - */ graphic->record(commands[i] ); } // render gui layer @@ -291,8 +301,7 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st for ( auto _ : layers ) { RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _; auto& blitter = layer->blitter; - if ( !blitter.initialized ) continue; - if ( blitter.descriptor.subpass != 0 ) continue; + if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != 0 ) continue; blitter.record(commands[i]); } } @@ -305,8 +314,7 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st for ( auto _ : layers ) { RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _; auto& blitter = layer->blitter; - if ( !blitter.initialized ) continue; - if ( blitter.descriptor.subpass != 1 ) continue; + if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != 1 ) continue; blitter.record(commands[i]); } } @@ -354,8 +362,8 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st imageBlitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageBlitRegion.dstSubresource.layerCount = 1; imageBlitRegion.dstOffsets[1] = { - swapchainRender.width > 0 ? swapchainRender.width : ext::vulkan::width, - swapchainRender.height > 0 ? swapchainRender.height : ext::vulkan::height, + swapchainRender.width > 0 ? swapchainRender.width : ext::vulkan::settings::width, + swapchainRender.height > 0 ? swapchainRender.height : ext::vulkan::settings::height, 1 }; diff --git a/engine/src/ext/vulkan/rendertarget.cpp b/engine/src/ext/vulkan/rendertarget.cpp index 3d9a6495..61d5f5ba 100644 --- a/engine/src/ext/vulkan/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendertarget.cpp @@ -18,8 +18,8 @@ void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFla passes.push_back(pass); } size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usage, VkImageLayout layout, bool blend, Attachment* attachment ) { - uint32_t width = this->width > 0 ? this->width : ext::vulkan::width; - uint32_t height = this->height > 0 ? this->height : ext::vulkan::height; + uint32_t width = this->width > 0 ? this->width : ext::vulkan::settings::width; + uint32_t height = this->height > 0 ? this->height : ext::vulkan::settings::height; if ( !attachment ) { attachments.resize(attachments.size()+1); @@ -49,7 +49,7 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa } VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; - switch ( ext::vulkan::msaa ) { + switch ( ext::vulkan::settings::msaa ) { case 64: samples = VK_SAMPLE_COUNT_64_BIT; break; case 32: samples = VK_SAMPLE_COUNT_32_BIT; break; case 16: samples = VK_SAMPLE_COUNT_16_BIT; break; @@ -142,8 +142,8 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) { { this->device = &device; } - uint32_t width = this->width > 0 ? this->width : ext::vulkan::width; - uint32_t height = this->height > 0 ? this->height : ext::vulkan::height; + uint32_t width = this->width > 0 ? this->width : ext::vulkan::settings::width; + uint32_t height = this->height > 0 ? this->height : ext::vulkan::settings::height; // resize attachments if necessary if ( initialized ) { diff --git a/engine/src/ext/vulkan/swapchain.cpp b/engine/src/ext/vulkan/swapchain.cpp index a8745476..4e719e8e 100644 --- a/engine/src/ext/vulkan/swapchain.cpp +++ b/engine/src/ext/vulkan/swapchain.cpp @@ -28,8 +28,8 @@ void ext::vulkan::Swapchain::initialize( Device& device ) { // Bind { this->device = &device; - if ( width == 0 ) width = ext::vulkan::width; - if ( height == 0 ) height = ext::vulkan::height; +// if ( width == 0 ) width = ext::vulkan::settings::width; +// if ( height == 0 ) height = ext::vulkan::settings::height; } // Set present VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; diff --git a/engine/src/ext/vulkan/vulkan.cpp b/engine/src/ext/vulkan/vulkan.cpp index 3403a0e8..331abaec 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -9,29 +9,32 @@ #include #include -uint32_t ext::vulkan::width = 1280; -uint32_t ext::vulkan::height = 720; -uint8_t ext::vulkan::msaa = 1; +uint32_t ext::vulkan::settings::width = 1280; +uint32_t ext::vulkan::settings::height = 720; +uint8_t ext::vulkan::settings::msaa = 1; +bool ext::vulkan::settings::validation = true; + +std::vector ext::vulkan::settings::validationFilters; +std::vector ext::vulkan::settings::requestedDeviceFeatures; +std::vector ext::vulkan::settings::requestedDeviceExtensions; +std::vector ext::vulkan::settings::requestedInstanceExtensions; + +bool ext::vulkan::settings::experimental::rebuildOnTickBegin = false; +bool ext::vulkan::settings::experimental::waitOnRenderEnd = false; +bool ext::vulkan::settings::experimental::individualPipelines = false; +bool ext::vulkan::settings::experimental::multithreadedCommandRecording = false; -bool ext::vulkan::validation = true; -bool ext::vulkan::rebuildOnTickStart = false; -bool ext::vulkan::waitOnRenderEnd = false; -std::vector ext::vulkan::validationFilters; -std::vector ext::vulkan::requestedDeviceFeatures; -std::vector ext::vulkan::requestedDeviceExtensions; -std::vector ext::vulkan::requestedInstanceExtensions; ext::vulkan::Device ext::vulkan::device; ext::vulkan::Allocator ext::vulkan::allocator; ext::vulkan::Swapchain ext::vulkan::swapchain; std::mutex ext::vulkan::mutex; -bool ext::vulkan::resized = false; -bool ext::vulkan::rebuild = false; -uint32_t ext::vulkan::currentBuffer = 0; -std::vector ext::vulkan::passes = { "BASE" }; +bool ext::vulkan::states::resized = false; +bool ext::vulkan::states::rebuild = false; +uint32_t ext::vulkan::states::currentBuffer = 0; + std::vector ext::vulkan::scenes; ext::vulkan::RenderMode* ext::vulkan::currentRenderMode = NULL; - std::vector ext::vulkan::renderModes = { new ext::vulkan::BaseRenderMode, }; @@ -55,51 +58,13 @@ VKAPI_ATTR VkBool32 VKAPI_CALL ext::vulkan::debugCallback( ) { // if ( messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT ) return VK_FALSE; std::string message = pCallbackData->pMessage; - for ( auto& filter : ext::vulkan::validationFilters ) { + for ( auto& filter : ext::vulkan::settings::validationFilters ) { if ( message.find(filter) != std::string::npos ) return VK_FALSE; } uf::iostream << "[Validation Layer] " << message << "\n"; return VK_FALSE; } -VkShaderModule ext::vulkan::loadShader(const char *filename, VkDevice device) { - std::ifstream is(filename, std::ios::binary | std::ios::in | std::ios::ate); - - if ( !is.is_open() ) { - uf::iostream << "Error: Could not open shader file \"" << filename << "\"" << "\n"; - return VK_NULL_HANDLE; - } - size_t size = is.tellg(); - is.seekg(0, std::ios::beg); - char* shaderCode = new char[size]; - is.read(shaderCode, size); - is.close(); - - assert(size > 0); - - VkShaderModule shaderModule; - VkShaderModuleCreateInfo moduleCreateInfo{}; - moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - moduleCreateInfo.codeSize = size; - moduleCreateInfo.pCode = (uint32_t*)shaderCode; - - VK_CHECK_RESULT(vkCreateShaderModule(device, &moduleCreateInfo, NULL, &shaderModule)); - - delete[] shaderCode; - return shaderModule; -} - -VkPipelineShaderStageCreateInfo ext::vulkan::loadShader( std::string filename, VkShaderStageFlagBits stage, VkDevice device, std::vector& shaderModules ) { - VkPipelineShaderStageCreateInfo shaderStage = {}; - shaderStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStage.stage = stage; - shaderStage.module = loadShader(filename.c_str(), device); - shaderStage.pName = "main"; - assert(shaderStage.module != VK_NULL_HANDLE); - shaderModules.push_back(shaderStage.module); - return shaderStage; -} - std::string ext::vulkan::errorString( VkResult result ) { switch ( result ) { #define STR(r) case VK_ ##r: return #r @@ -181,7 +146,7 @@ ext::vulkan::RenderMode& ext::vulkan::addRenderMode( ext::vulkan::RenderMode* mo renderModes.push_back(mode); std::cout << "Adding RenderMode: " << name << ": " << mode->getType() << std::endl; // reorder - ext::vulkan::rebuild = true; + ext::vulkan::states::rebuild = true; return *mode; } ext::vulkan::RenderMode& ext::vulkan::getRenderMode( const std::string& name, bool isName ) { @@ -221,7 +186,7 @@ void ext::vulkan::removeRenderMode( ext::vulkan::RenderMode* mode, bool free ) { renderModes.erase( std::remove( renderModes.begin(), renderModes.end(), mode ), renderModes.end() ); mode->destroy(); if ( free ) delete mode; - ext::vulkan::rebuild = true; + ext::vulkan::states::rebuild = true; } void ext::vulkan::initialize( uint8_t stage ) { @@ -248,10 +213,28 @@ void ext::vulkan::initialize( uint8_t stage ) { if ( !renderMode ) continue; renderMode->initialize(device); } + std::vector> jobs; + for ( auto& renderMode : renderModes ) { + if ( !renderMode ) continue; + if ( settings::experimental::individualPipelines ) renderMode->bindPipelines(); + if ( settings::experimental::multithreadedCommandRecording ) { + jobs.emplace_back([&]{ + renderMode->createCommandBuffers(); + return 0; + }); + } else { + renderMode->createCommandBuffers(); + } + } + if ( !jobs.empty() ) { + uf::thread::batchWorkers( jobs ); + } + /* for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; renderMode->createCommandBuffers(); } + */ } break; case 1: { std::function filter = [&]( uf::Entity* entity ) { @@ -260,7 +243,7 @@ void ext::vulkan::initialize( uint8_t stage ) { if ( graphic.initialized ) return; graphic.initializePipeline(); - ext::vulkan::rebuild = true; + ext::vulkan::states::rebuild = true; }; for ( uf::Scene* scene : ext::vulkan::scenes ) { if ( !scene ) continue; @@ -268,10 +251,28 @@ void ext::vulkan::initialize( uint8_t stage ) { } } case 2: { + /* for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; renderMode->createCommandBuffers(); } + */ + std::vector> jobs; + for ( auto& renderMode : renderModes ) { + if ( !renderMode ) continue; + if ( settings::experimental::individualPipelines ) renderMode->bindPipelines(); + if ( settings::experimental::multithreadedCommandRecording ) { + jobs.emplace_back([&]{ + renderMode->createCommandBuffers(); + return 0; + }); + } else { + renderMode->createCommandBuffers(); + } + } + if ( !jobs.empty() ) { + uf::thread::batchWorkers( jobs ); + } } break; default: { throw std::runtime_error("invalid stage id"); @@ -280,8 +281,8 @@ void ext::vulkan::initialize( uint8_t stage ) { } void ext::vulkan::tick() { ext::vulkan::mutex.lock(); - if ( ext::vulkan::resized || ext::vulkan::rebuildOnTickStart ) { - ext::vulkan::rebuild = true; + if ( ext::vulkan::states::resized || ext::vulkan::settings::experimental::rebuildOnTickBegin ) { + ext::vulkan::states::rebuild = true; } std::function filter = [&]( uf::Entity* entity ) { @@ -289,7 +290,7 @@ void ext::vulkan::tick() { ext::vulkan::Graphic& graphic = entity->getComponent(); if ( graphic.initialized || !graphic.process || graphic.initialized ) return; graphic.initializePipeline(); - ext::vulkan::rebuild = true; + ext::vulkan::states::rebuild = true; }; for ( uf::Scene* scene : ext::vulkan::scenes ) { if ( !scene ) continue; @@ -299,7 +300,7 @@ void ext::vulkan::tick() { if ( !renderMode ) continue; if ( !renderMode->device ) { renderMode->initialize(ext::vulkan::device); - ext::vulkan::rebuild = true; + ext::vulkan::states::rebuild = true; } renderMode->tick(); } @@ -307,21 +308,24 @@ void ext::vulkan::tick() { std::vector> jobs; for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; - if ( ext::vulkan::rebuild || renderMode->rebuild ) { - jobs.emplace_back([&]{ + if ( ext::vulkan::states::rebuild || renderMode->rebuild ) { + if ( settings::experimental::individualPipelines ) renderMode->bindPipelines(); + if ( settings::experimental::multithreadedCommandRecording ) { + jobs.emplace_back([&]{ + renderMode->createCommandBuffers(); + return 0; + }); + } else { renderMode->createCommandBuffers(); - return 0; - }); + } } } if ( !jobs.empty() ) { - // std::cout << "Batching " << jobs.size() << " command buffer jobs" << std::endl; uf::thread::batchWorkers( jobs ); - // std::cout << "Done" << std::endl; } - ext::vulkan::rebuild = false; - ext::vulkan::resized = false; + ext::vulkan::states::rebuild = false; + ext::vulkan::states::resized = false; ext::vulkan::mutex.unlock(); } void ext::vulkan::render() { @@ -346,19 +350,14 @@ void ext::vulkan::render() { } ext::vulkan::currentRenderMode = NULL; - if ( ext::vulkan::waitOnRenderEnd ) { - for ( auto& renderMode : renderModes ) { - if ( !renderMode ) continue; - if ( !renderMode->execute ) continue; - renderMode->synchronize(); - } - vkDeviceWaitIdle( device ); + if ( ext::vulkan::settings::experimental::waitOnRenderEnd ) { + synchronize(); } ext::vulkan::mutex.unlock(); } void ext::vulkan::destroy() { ext::vulkan::mutex.lock(); - vkDeviceWaitIdle( device ); + synchronize(); Texture2D::empty.destroy(); @@ -385,6 +384,17 @@ void ext::vulkan::destroy() { device.destroy(); ext::vulkan::mutex.unlock(); } +void ext::vulkan::synchronize( uint8_t flag ) { + if ( flag & 0b01 ) { + for ( auto& renderMode : renderModes ) { + if ( !renderMode ) continue; + if ( !renderMode->execute ) continue; + renderMode->synchronize(); + } + } + if ( flag & 0b10 ) + vkDeviceWaitIdle( device ); +} std::string ext::vulkan::allocatorStats() { char* statsString = nullptr; diff --git a/ext/behaviors/craeture/behavior.cpp b/ext/behaviors/craeture/behavior.cpp index edeca4ba..b9088d87 100644 --- a/ext/behaviors/craeture/behavior.cpp +++ b/ext/behaviors/craeture/behavior.cpp @@ -76,6 +76,7 @@ void ext::CraetureBehavior::initialize( uf::Object& self ) { pod::Vector3 normal; float scale = metadata["system"]["physics"]["collision"].asFloat(); float depth = json["depth"].asFloat() * scale; + // if ( fabs(depth) < 0.005 ) return "false"; //std::cout << "Collision depth: " << depth << std::endl; normal.x = json["normal"][0].asFloat(); normal.y = json["normal"][1].asFloat(); @@ -84,6 +85,7 @@ void ext::CraetureBehavior::initialize( uf::Object& self ) { transform.position -= correction; + if ( normal.x == 1 || normal.x == -1 ) physics.linear.velocity.x = 0; if ( normal.y == 1 || normal.y == -1 ) physics.linear.velocity.y = 0; if ( normal.z == 1 || normal.z == -1 ) physics.linear.velocity.z = 0; diff --git a/ext/behaviors/light/behavior.cpp b/ext/behaviors/light/behavior.cpp index b2598961..67631317 100644 --- a/ext/behaviors/light/behavior.cpp +++ b/ext/behaviors/light/behavior.cpp @@ -12,27 +12,26 @@ void ext::LightBehavior::initialize( uf::Object& self ) { auto& metadata = this->getComponent(); auto& transform = this->getComponent>(); auto& camera = this->getComponent(); + auto& scene = uf::scene::getCurrentScene(); + auto& controller = scene.getController(); + if ( metadata["light"]["shadows"]["enabled"].asBool() ) { auto& renderMode = this->getComponent(); std::string name = "RT:" + std::to_string((int) this->getUid()); uf::renderer::addRenderMode( &renderMode, name ); - { - auto& scene = uf::scene::getCurrentScene(); - auto& controller = scene.getController(); - - camera = controller.getComponent(); - camera.getTransform() = {}; - camera.setStereoscopic(false); - if ( metadata["light"]["shadows"]["fov"].isNumeric() ) { - camera.setFov( metadata["light"]["shadows"]["fov"].asFloat() ); - camera.updateProjection(); - } - if ( metadata["light"]["radius"].isArray() ) { - auto bounds = camera.getBounds(); - bounds.x = metadata["light"]["radius"][0].asFloat(); - bounds.y = metadata["light"]["radius"][1].asFloat(); - camera.setBounds(bounds); - } + renderMode.blitter.process = false; + camera = controller.getComponent(); + camera.getTransform() = {}; + camera.setStereoscopic(false); + if ( metadata["light"]["shadows"]["fov"].isNumeric() ) { + camera.setFov( metadata["light"]["shadows"]["fov"].asFloat() ); + camera.updateProjection(); + } + if ( metadata["light"]["radius"].isArray() ) { + auto bounds = camera.getBounds(); + bounds.x = metadata["light"]["radius"][0].asFloat(); + bounds.y = metadata["light"]["radius"][1].asFloat(); + camera.setBounds(bounds); } if ( metadata["light"]["shadows"]["resolution"].isArray() ) { renderMode.width = metadata["light"]["shadows"]["resolution"][0].asUInt64(); diff --git a/ext/behaviors/scene/behavior.cpp b/ext/behaviors/scene/behavior.cpp index 5f7a3a24..80107c8d 100644 --- a/ext/behaviors/scene/behavior.cpp +++ b/ext/behaviors/scene/behavior.cpp @@ -109,10 +109,10 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) { return "true"; }); /* store viewport size */ { - metadata["system"]["window"]["size"]["x"] = uf::renderer::width; - metadata["system"]["window"]["size"]["y"] = uf::renderer::height; - ext::gui::size.current.x = uf::renderer::width; - ext::gui::size.current.y = uf::renderer::height; + metadata["system"]["window"]["size"]["x"] = uf::renderer::settings::width; + metadata["system"]["window"]["size"]["y"] = uf::renderer::settings::height; + ext::gui::size.current.x = uf::renderer::settings::width; + ext::gui::size.current.y = uf::renderer::settings::height; this->addHook( "window:Resized", [&](const std::string& event)->std::string{ uf::Serializer json = event; @@ -413,7 +413,8 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { } // check if we actually do need to update our pipeline, to avoid the command buffer rebuild cost if ( shouldUpdate ) { - blitter.getPipeline().update( blitter ); + // blitter.getPipeline().update( blitter ); + blitter.updatePipelines(); } } shader->updateBuffer( (void*) buffer, len, 0, false ); diff --git a/ext/gui/behavior.cpp b/ext/gui/behavior.cpp index 396ee1f5..81cb2721 100644 --- a/ext/gui/behavior.cpp +++ b/ext/gui/behavior.cpp @@ -825,6 +825,7 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { // graphic.descriptor.indices = 0; graphic.initializeGeometry( mesh ); graphic.getPipeline().update( graphic ); + // graphic.updatePipelines(); // uf::renderer::rebuild = true; /* diff --git a/ext/gui/manager/behavior.cpp b/ext/gui/manager/behavior.cpp index b6619dc0..96d33c06 100644 --- a/ext/gui/manager/behavior.cpp +++ b/ext/gui/manager/behavior.cpp @@ -32,8 +32,8 @@ ext::gui::Size ext::gui::size = { .current = { - uf::renderer::width, - uf::renderer::height, + uf::renderer::settings::width, + uf::renderer::settings::height, }, .reference = { 1920, @@ -47,8 +47,8 @@ EXT_BEHAVIOR_REGISTER_AS_OBJECT(GuiManagerBehavior, GuiManager) #define this (&self) void ext::GuiManagerBehavior::initialize( uf::Object& self ) { { - ext::gui::size.current.x = uf::renderer::width; - ext::gui::size.current.y = uf::renderer::height; + ext::gui::size.current.x = uf::renderer::settings::width; + ext::gui::size.current.y = uf::renderer::settings::height; } // add gui render mode if ( !uf::renderer::hasRenderMode( "Gui", true ) ) { diff --git a/ext/main.cpp b/ext/main.cpp index ddf22e9e..cbe2918e 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -59,6 +59,7 @@ namespace { double prevTime = 0; double curTime = 0; double deltaTime = 0; + size_t frames = 0; } times; uf::Serializer config; @@ -69,6 +70,7 @@ std::vector ext::arguments; void EXT_API ext::initialize() { ::config = ext::getConfig(); /* Arguments */ { + bool modified = false; auto& arguments = ::config["arguments"]; for ( auto& arg : ext::arguments ) { // store raw argument @@ -88,11 +90,12 @@ void EXT_API ext::initialize() { traversal = &((*traversal)[key]); } *traversal = value; + modified = true; } } } uf::iostream << "Arguments: " << uf::Serializer(arguments) << "\n"; - uf::iostream << "New config: " << ::config << "\n"; + if ( modified ) uf::iostream << "New config: " << ::config << "\n"; } /* Seed */ { @@ -138,23 +141,23 @@ void EXT_API ext::initialize() { { size_t size = deduceSize( ::config["engine"]["memory pool"]["size"] ); uf::MemoryPool::globalOverride = ::config["engine"]["memory pool"]["globalOverride"].asBool(); - std::cout << "Requesting " << (int) size << " bytes for global memory pool: " << &uf::MemoryPool::global << std::endl; + uf::iostream << "Requesting " << (int) size << " bytes for global memory pool: " << &uf::MemoryPool::global << "\n"; uf::MemoryPool::global.initialize( size ); uf::MemoryPool::subPool = ::config["engine"]["memory pool"]["subPools"].asBool(); if ( size <= 0 || uf::MemoryPool::subPool ) { { size_t size = deduceSize( ::config["engine"]["memory pools"]["component"] ); - std::cout << "Requesting " << (int) size << " bytes for component memory pool: " << &uf::component::memoryPool << std::endl; + uf::iostream << "Requesting " << (int) size << " bytes for component memory pool: " << &uf::component::memoryPool << "\n"; uf::component::memoryPool.initialize( size ); } { size_t size = deduceSize( ::config["engine"]["memory pools"]["userdata"] ); - std::cout << "Requesting " << (int) size << " bytes for userdata memory pool: " << &uf::userdata::memoryPool << std::endl; + uf::iostream << "Requesting " << (int) size << " bytes for userdata memory pool: " << &uf::userdata::memoryPool << "\n"; uf::userdata::memoryPool.initialize( size ); } { size_t size = deduceSize( ::config["engine"]["memory pools"]["entity"] ); - std::cout << "Requesting " << (int) size << " bytes for entity memory pool: " << &uf::Entity::memoryPool << std::endl; + uf::iostream << "Requesting " << (int) size << " bytes for entity memory pool: " << &uf::Entity::memoryPool << "\n"; uf::Entity::memoryPool.initialize( size ); } } @@ -178,27 +181,35 @@ void EXT_API ext::initialize() { uf::thread::limiter = 1.0 / ::config["engine"]["threads"]["frame limiter"].asDouble(); } // Set worker threads + if ( ::config["engine"]["threads"]["workers"].asString() == "auto" ) { + auto threads = std::max( 1, (int) std::thread::hardware_concurrency() - 1 ); + ::config["engine"]["threads"]["workers"] = threads; + uf::iostream << "Using " << threads << " worker threads" << "\n"; + } uf::thread::workers = ::config["engine"]["threads"]["workers"].asUInt64(); // Enable valiation layer - uf::renderer::validation = ::config["engine"]["ext"]["vulkan"]["validation"]["enabled"].asBool(); - if ( ::config["engine"]["ext"]["vulkan"]["validation"]["enabled"].isNumeric() ) - uf::renderer::msaa = ::config["engine"]["ext"]["vulkan"]["msaa"].asUInt64(); + uf::renderer::settings::validation = ::config["engine"]["ext"]["vulkan"]["validation"]["enabled"].asBool(); + + if ( ::config["engine"]["ext"]["vulkan"]["msaa"].isNumeric() ) + uf::renderer::settings::msaa = ::config["engine"]["ext"]["vulkan"]["msaa"].asUInt64(); - uf::renderer::rebuildOnTickStart = ::config["engine"]["ext"]["vulkan"]["validation"]["rebuild on tick begin"].asBool(); - uf::renderer::waitOnRenderEnd = ::config["engine"]["ext"]["vulkan"]["validation"]["wait on render end"].asBool(); - for ( int i = 0; i < ::config["engine"]["ext"]["vulkan"]["validation"]["filters"].size(); ++i ) { - uf::renderer::validationFilters.push_back( ::config["engine"]["ext"]["vulkan"]["validation"]["filters"][i].asString() ); + uf::renderer::settings::validationFilters.push_back( ::config["engine"]["ext"]["vulkan"]["validation"]["filters"][i].asString() ); } for ( int i = 0; i < ::config["engine"]["ext"]["vulkan"]["extensions"]["device"].size(); ++i ) { - uf::renderer::requestedDeviceExtensions.push_back( ::config["engine"]["ext"]["vulkan"]["extensions"]["device"][i].asString() ); + uf::renderer::settings::requestedDeviceExtensions.push_back( ::config["engine"]["ext"]["vulkan"]["extensions"]["device"][i].asString() ); } for ( int i = 0; i < ::config["engine"]["ext"]["vulkan"]["extensions"]["instance"].size(); ++i ) { - uf::renderer::requestedInstanceExtensions.push_back( ::config["engine"]["ext"]["vulkan"]["extensions"]["instance"][i].asString() ); + uf::renderer::settings::requestedInstanceExtensions.push_back( ::config["engine"]["ext"]["vulkan"]["extensions"]["instance"][i].asString() ); } for ( int i = 0; i < ::config["engine"]["ext"]["vulkan"]["features"].size(); ++i ) { - uf::renderer::requestedDeviceFeatures.push_back( ::config["engine"]["ext"]["vulkan"]["features"][i].asString() ); + uf::renderer::settings::requestedDeviceFeatures.push_back( ::config["engine"]["ext"]["vulkan"]["features"][i].asString() ); } + uf::renderer::settings::experimental::rebuildOnTickBegin = ::config["engine"]["ext"]["vulkan"]["experimental"]["rebuild on tick begin"].asBool(); + uf::renderer::settings::experimental::waitOnRenderEnd = ::config["engine"]["ext"]["vulkan"]["experimental"]["wait on render end"].asBool(); + uf::renderer::settings::experimental::individualPipelines = ::config["engine"]["ext"]["vulkan"]["experimental"]["individual pipelines"].asBool(); + uf::renderer::settings::experimental::multithreadedCommandRecording = ::config["engine"]["ext"]["vulkan"]["experimental"]["multithreaded command recording"].asBool(); + ext::openvr::enabled = ::config["engine"]["ext"]["vr"]["enable"].asBool(); ext::openvr::swapEyes = ::config["engine"]["ext"]["vr"]["swap eyes"].asBool(); if ( ::config["engine"]["ext"]["vr"]["dominatEye"].isNumeric() ) @@ -234,9 +245,6 @@ void EXT_API ext::initialize() { else if ( ::config["engine"]["render modes"]["deferred"].asBool() ) uf::renderer::addRenderMode( new uf::renderer::DeferredRenderMode, "" ); - // if ( ::config["engine"]["render modes"]["compute"].asBool() ) - // uf::renderer::addRenderMode( new uf::renderer::ComputeRenderMode, "C:RT:0" ); - if ( ext::openvr::enabled ) { ext::openvr::initialize(); @@ -247,7 +255,7 @@ void EXT_API ext::initialize() { renderMode.width = width; renderMode.height = height; - std::cout << "Recommended VR Resolution: " << width << ", " << height << std::endl; + uf::iostream << "Recommended VR Resolution: " << width << ", " << height << "\n"; } uf::renderer::initialize(); @@ -271,9 +279,8 @@ void EXT_API ext::initialize() { /* Add hooks */ { uf::hooks.addHook( "game:LoadScene", [&](const std::string& event)->std::string{ uf::Serializer json = event; - std::cout << "SCENE CHANGE: " << event << std::endl; - uf::renderer::mutex.lock(); - uf::renderer::mutex.unlock(); + uf::iostream << "SCENE CHANGE: " << event << "\n"; + uf::renderer::synchronize(); uf::scene::unloadScene(); auto& scene = uf::scene::loadScene( json["scene"].asString() ); auto& metadata = scene.getComponent(); @@ -282,7 +289,7 @@ void EXT_API ext::initialize() { }); uf::hooks.addHook( "system:Quit", [&](const std::string& event)->std::string{ - std::cout << "system:Quit: " << event << std::endl; + uf::iostream << "system:Quit: " << event << "\n"; ext::ready = false; return "true"; }); @@ -304,8 +311,6 @@ void EXT_API ext::tick() { times.curTime = times.sys.elapsed().asDouble(); times.deltaTime = times.curTime - times.prevTime; } - static uf::Timer timer(false); - if ( !timer.running() ) timer.start(); /* Print World Tree */ { static uf::Timer timer(false); @@ -322,7 +327,7 @@ void EXT_API ext::tick() { }; for ( uf::Scene* scene : uf::renderer::scenes ) { if ( !scene ) continue; - std::cout << "Scene: " << scene->getName() << ": " << scene << std::endl; + uf::iostream << "Scene: " << scene->getName() << ": " << scene << "\n"; scene->process(filter, 1); } } @@ -335,13 +340,13 @@ void EXT_API ext::tick() { for ( int i = 0; i < indent; ++i ) uf::iostream << "\t"; uf::iostream << entity->getName() << ": " << entity->getUid() << " ["; for ( auto& behavior : entity->getBehaviors() ) { - std::cout << uf::instantiator::behaviors->names[behavior.type] << ", "; + uf::iostream << uf::instantiator::behaviors->names[behavior.type] << ", "; } uf::iostream << "]\n"; }; for ( uf::Scene* scene : uf::renderer::scenes ) { if ( !scene ) continue; - std::cout << "Scene: " << scene->getName() << ": " << scene << std::endl; + uf::iostream << "Scene: " << scene->getName() << ": " << scene << "\n"; scene->process(filter, 1); } uf::Serializer instantiator; @@ -357,7 +362,7 @@ void EXT_API ext::tick() { instantiator["behaviors"][i++] = pair.second; } } - std::cout << instantiator << std::endl; + uf::iostream << instantiator << "\n"; } } /* Print Entity Information */ { @@ -431,19 +436,26 @@ void EXT_API ext::tick() { /* FPS Print */ if ( ::config["engine"]["debug"]["framerate"]["print"].asBool() ) { static uf::Timer timer(false); if ( !timer.running() ) timer.start(); - if ( timer.elapsed().asDouble() >= ::config["engine"]["debug"]["framerate"]["every"].asDouble() ) { timer.reset(); - std::cout << "Framerate: " << (1.0/times.deltaTime) << " FPS | Frametime: " << (times.deltaTime * 1000) << "ms" << std::endl; + ++::times.frames; + double every = ::config["engine"]["debug"]["framerate"]["every"].asDouble(); + double time = 0; + if ( (time = timer.elapsed().asDouble()) >= every ) { timer.reset(); +// uf::iostream << "Framerate: " << (1.0/times.deltaTime) << " FPS | Frametime: " << (times.deltaTime * 1000) << "ms" << "\n"; + uf::iostream << "System: " << (every * 1000.0/::times.frames) << " ms/frame | Time: " << time << " | Frames: " << ::times.frames << " | FPS: " << ::times.frames / time << "\n"; + ::times.frames = 0; } } /* Frame limiter of sorts I guess */ if ( uf::thread::limiter > 0 ) { + static uf::Timer timer(false); + if ( !timer.running() ) timer.start(); auto elapsed = timer.elapsed().asMilliseconds(); long long sleep = (uf::thread::limiter * 1000) - elapsed; if ( sleep > 0 ) { if ( ::config["engine"]["debug"]["framerate"]["print"].asBool() ) { - std::cout << "Frame limiting: " << elapsed << "ms exceeds limit, sleeping for " << elapsed << "ms" << std::endl; + // uf::iostream << "Frame limiting: " << elapsed << "ms exceeds limit, sleeping for " << elapsed << "ms" << "\n"; } - std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); + // std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); } timer.reset(); } @@ -472,9 +484,9 @@ void EXT_API ext::terminate() { /* Flush input buffer */ { - io.output << io.input << std::endl; - for ( const auto& str : uf::iostream.getHistory() ) io.output << str << std::endl; - io.output << "\nTerminated after " << times.sys.elapsed().asDouble() << " seconds" << std::endl; + io.output << io.input << "\n"; + for ( const auto& str : uf::iostream.getHistory() ) io.output << str << "\n"; + io.output << "\nTerminated after " << times.sys.elapsed().asDouble() << " seconds" << "\n"; io.output.close(); } @@ -532,7 +544,7 @@ std::string EXT_API ext::getConfig() { config.fallback["engine"]["hook"]["mode"] = "Readable"; config.fallback["engine"]["limiters"]["framerate"] = 60; config.fallback["engine"]["limiters"]["deltaTime"] = 120; - config.fallback["engine"]["threads"]["workers"] = 1; + config.fallback["engine"]["threads"]["workers"] = "auto"; config.fallback["engine"]["threads"]["frame limiter"] = 144; config.fallback["engine"]["memory pool"]["size"] = "512 MiB"; config.fallback["engine"]["memory pool"]["globalOverride"] = false; diff --git a/ext/scenes/worldscape/terrain/behavior.cpp b/ext/scenes/worldscape/terrain/behavior.cpp index 49a40e40..174b40e1 100644 --- a/ext/scenes/worldscape/terrain/behavior.cpp +++ b/ext/scenes/worldscape/terrain/behavior.cpp @@ -86,8 +86,9 @@ void ext::TerrainBehavior::initialize( uf::Object& self ) { graphic.initializeGeometry( mesh ); graphic.getPipeline().update( graphic ); + // graphic.updatePipelines(); graphic.process = true; - uf::renderer::rebuild = true; + uf::renderer::states::rebuild = true; return "true"; }); @@ -119,8 +120,7 @@ void ext::TerrainBehavior::initialize( uf::Object& self ) { {"./data/shaders/terrain.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT}, {"./data/shaders/terrain."+suffix+"frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT} }); - - uf::renderer::rebuildOnTickStart = false; + // uf::renderer::rebuildOnTickStart = false; } this->generate();