Commit for 2020.10.25.7z

This commit is contained in:
mrq 2020-10-25 00:00:00 -05:00
parent 7027ce2db7
commit 360e921722
45 changed files with 876 additions and 449 deletions

View File

@ -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/

View File

@ -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];

View File

@ -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);
}

View File

@ -7,6 +7,7 @@
#include <uf/spec/terminal/terminal.h>
#include <uf/utils/hook/hook.h>
#include <uf/utils/thread/thread.h>
#include <uf/utils/renderer/renderer.h>
#include <uf/ext/vulkan/vulkan.h>
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" ) {

View File

@ -1,7 +1,6 @@
#pragma once
#include <uf/config.h>
#include <discord/discord.h>
namespace ext {
namespace discord {

View File

@ -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<std::pair<std::string, VkShaderStageFlagBits>>& );
};
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<typename T, typename U>
void initializeGeometry( uf::BaseMesh<T, U>& 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 );
};
}
}

View File

@ -35,6 +35,7 @@ namespace ext {
virtual void initialize( Device& device );
virtual void createCommandBuffers();
virtual void createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics );
virtual void bindPipelines();
virtual void bindPipelines( const std::vector<ext::vulkan::Graphic*>& graphics );
virtual void tick();
virtual void render();

View File

@ -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

View File

@ -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<VkShaderModule>& 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<std::string> validationFilters;
extern UF_API std::vector<std::string> requestedDeviceFeatures;
extern UF_API std::vector<std::string> requestedDeviceExtensions;
extern UF_API std::vector<std::string> 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<std::string> validationFilters;
extern UF_API std::vector<std::string> requestedDeviceFeatures;
extern UF_API std::vector<std::string> requestedDeviceExtensions;
extern UF_API std::vector<std::string> 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<std::string> passes;
extern UF_API std::vector<RenderMode*> renderModes;
extern UF_API std::vector<uf::Scene*> 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();
}
}

View File

@ -119,7 +119,7 @@ void uf::ObjectBehavior::destroy( uf::Object& self ) {
if ( this->hasComponent<uf::Graphic>() ) {
auto& graphic = this->getComponent<uf::Graphic>();
graphic.destroy();
uf::renderer::rebuild = true;
uf::renderer::states::rebuild = true;
}
}
void uf::ObjectBehavior::tick( uf::Object& self ) {

View File

@ -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)

View File

@ -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

View File

@ -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<void(Result)> ca
}
} // namespace discord
#endif

View File

@ -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<void(Result, char const*)> call
}
} // namespace discord
#endif

View File

@ -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

View File

@ -1,4 +1,5 @@
#include <uf/ext/discord/discord.h>
#if defined(UF_USE_DISCORD)
#define _CRT_SECURE_NO_WARNINGS
#include <array>
@ -437,4 +438,10 @@ void UF_API ext::::discord::initialize() {
void UF_API ext::::discord::tick() {
DISCORD_REQUIRE(app.core->run_callbacks(app.core));
}
*/
*/
#else
void UF_API ext::discord::initialize(){
}
void UF_API ext::discord::tick(){
}
#endif

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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<void(Result)> callback)
}
} // namespace discord
#endif

View File

@ -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

View File

@ -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

View File

@ -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<void(Result)> ca
}
} // namespace discord
#endif

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -2,7 +2,7 @@
#include <uf/utils/io/iostream.h>
#include <uf/utils/string/ext.h>
#include <uf/utils/string/io.h>
#include <uf/utils/renderer/renderer.h>
#include <uf/ext/vulkan/vulkan.h>
#include <uf/ext/vulkan/rendermodes/stereoscopic_deferred.h>
#include <stdlib.h>
@ -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];

View File

@ -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<VkLayerProperties> availableLayers(layerCount);
@ -527,14 +527,14 @@ void ext::vulkan::Device::initialize() {
}
//
// Get extensions
std::vector<std::string> requestedExtensions = window->getExtensions( ext::vulkan::validation );
std::vector<std::string> 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<const char*> 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<uint32_t>(instanceExtensions.size());
createInfo.ppEnabledExtensionNames = instanceExtensions.data();
if ( ext::vulkan::validation ) {
if ( ext::vulkan::settings::validation ) {
createInfo.enabledLayerCount = static_cast<uint32_t>(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<std::string> 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

View File

@ -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<VkDescriptorSetLayoutBinding> descriptorSetLayoutBindings;
std::vector<VkPushConstantRange> 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<VkPipelineColorBlendAttachmentState> 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<VkVertexInputBindingDescription> 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<VkVertexInputAttributeDescription> 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<VkWriteDescriptorSet> writeDescriptorSets;
std::vector<VkDescriptorSetLayoutBinding> 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<VkDescriptorBufferInfo*>(&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 <uf/utils/string/hash.h>
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() );
}

View File

@ -34,16 +34,7 @@ void ext::vulkan::RenderMode::createCommandBuffers() {
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
if ( !entity->hasComponent<uf::Graphic>() ) return;
ext::vulkan::Graphic& graphic = entity->getComponent<uf::Graphic>();
if ( !graphic.initialized ) return;
if ( !graphic.process ) return;
/*
if ( !entity->hasComponent<uf::Mesh>() ) return;
uf::MeshBase& mesh = entity->getComponent<uf::Mesh>();
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<ext::vulkan::Graphic*>& graphics ) {
}
void ext::vulkan::RenderMode::bindPipelines() {
this->execute = true;
std::vector<ext::vulkan::Graphic*> graphics;
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
if ( !entity->hasComponent<uf::Graphic>() ) return;
ext::vulkan::Graphic& graphic = entity->getComponent<uf::Graphic>();
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<ext::vulkan::Graphic*>& 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::vector<ext::vulkan::Grap
void ext::vulkan::RenderMode::render() {
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Get next image in the swap chain (back/front buffer)
VK_CHECK_RESULT(swapchain.acquireNextImage(&currentBuffer, 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 )));
}

View File

@ -21,8 +21,8 @@ std::string ext::vulkan::BaseRenderMode::getType() const {
void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& 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::vector<ext::v
void ext::vulkan::BaseRenderMode::tick() {
ext::vulkan::RenderMode::tick();
if ( ext::vulkan::resized ) {
if ( ext::vulkan::states::resized ) {
this->destroy();
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 = {};

View File

@ -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();

View File

@ -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<ext::vulkan::Graphic*>& 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<RenderMode*> layers = ext::vulkan::getRenderModes(std::vector<std::string>{"RenderTarget", "Compute"}, false);
auto& scene = uf::scene::getCurrentScene();
@ -246,21 +235,6 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
// transition layers for read
for ( auto layer : layers ) {
layer->pipelineBarrier( 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::vector<ex
for ( auto graphic : graphics ) {
// only draw graphics that are assigned to this type of render mode
if ( graphic->descriptor.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::vector<ex
{
blitter.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 != 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::vector<ex
for ( auto layer : layers ) {
layer->pipelineBarrier( 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;
}
*/
}
}

View File

@ -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<pod::Vertex_2F2F, uint32_t> 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<ext::vulkan::Graphic*>& 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]);
}

View File

@ -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<pod::Vertex_2F2F, uint16_t> 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<uf::Serializer>();
@ -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<ext::vulkan::Graphic*>& 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>();
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
};

View File

@ -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 ) {

View File

@ -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;

View File

@ -9,29 +9,32 @@
#include <fstream>
#include <atomic>
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<std::string> ext::vulkan::settings::validationFilters;
std::vector<std::string> ext::vulkan::settings::requestedDeviceFeatures;
std::vector<std::string> ext::vulkan::settings::requestedDeviceExtensions;
std::vector<std::string> 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<std::string> ext::vulkan::validationFilters;
std::vector<std::string> ext::vulkan::requestedDeviceFeatures;
std::vector<std::string> ext::vulkan::requestedDeviceExtensions;
std::vector<std::string> 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<std::string> 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<uf::Scene*> ext::vulkan::scenes;
ext::vulkan::RenderMode* ext::vulkan::currentRenderMode = NULL;
std::vector<ext::vulkan::RenderMode*> 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<VkShaderModule>& 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<std::function<int()>> 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<void(uf::Entity*)> 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<std::function<int()>> 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<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
@ -289,7 +290,7 @@ void ext::vulkan::tick() {
ext::vulkan::Graphic& graphic = entity->getComponent<uf::Graphic>();
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<std::function<int()>> 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;

View File

@ -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;

View File

@ -12,27 +12,26 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<uf::Serializer>();
auto& transform = this->getComponent<pod::Transform<>>();
auto& camera = this->getComponent<uf::Camera>();
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
if ( metadata["light"]["shadows"]["enabled"].asBool() ) {
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
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<uf::Camera>();
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<uf::Camera>();
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();

View File

@ -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 );

View File

@ -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;
/*

View File

@ -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 ) ) {

View File

@ -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<std::string> 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<uf::Serializer>();
@ -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<long long> timer(false);
if ( !timer.running() ) timer.start();
/* Print World Tree */ {
static uf::Timer<long long> 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<long long> 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<long long> 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;

View File

@ -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();