Commit for 2021.02.05.7z
This commit is contained in:
parent
77f24467e9
commit
910039a877
@ -1,11 +1,27 @@
|
|||||||
#version 450
|
#version 450
|
||||||
#extension GL_EXT_samplerless_texture_functions : require
|
#extension GL_EXT_samplerless_texture_functions : require
|
||||||
|
|
||||||
#define UF_DEFERRED_SAMPLING 0
|
#define POISSON_DISK 4
|
||||||
|
#define RAY_MARCH_FOG 0
|
||||||
|
#define UF_DEFERRED_SAMPLING 1
|
||||||
|
|
||||||
layout (constant_id = 0) const uint LIGHTS = 256;
|
layout (constant_id = 0) const uint TEXTURES = 256;
|
||||||
layout (constant_id = 1) const uint TEXTURES = 256;
|
|
||||||
|
|
||||||
|
struct Light {
|
||||||
|
vec3 position;
|
||||||
|
float radius;
|
||||||
|
|
||||||
|
vec3 color;
|
||||||
|
float power;
|
||||||
|
|
||||||
|
int type;
|
||||||
|
int mapIndex;
|
||||||
|
float depthBias;
|
||||||
|
float padding;
|
||||||
|
|
||||||
|
mat4 view;
|
||||||
|
mat4 projection;
|
||||||
|
};
|
||||||
struct Material {
|
struct Material {
|
||||||
vec4 colorBase;
|
vec4 colorBase;
|
||||||
vec4 colorEmissive;
|
vec4 colorEmissive;
|
||||||
@ -54,7 +70,9 @@ layout (input_attachment_index = 3, binding = 4) uniform subpassInput samplerDep
|
|||||||
|
|
||||||
layout (binding = 5) uniform sampler3D samplerNoise;
|
layout (binding = 5) uniform sampler3D samplerNoise;
|
||||||
layout (binding = 6) uniform sampler2D samplerTextures[TEXTURES];
|
layout (binding = 6) uniform sampler2D samplerTextures[TEXTURES];
|
||||||
layout (binding = 7) uniform sampler2D samplerShadows[LIGHTS];
|
layout (std140, binding = 7) readonly buffer Lights {
|
||||||
|
Light lights[];
|
||||||
|
};
|
||||||
layout (std140, binding = 8) readonly buffer Materials {
|
layout (std140, binding = 8) readonly buffer Materials {
|
||||||
Material materials[];
|
Material materials[];
|
||||||
};
|
};
|
||||||
@ -71,14 +89,6 @@ layout (location = 1) in flat uint inPushConstantPass;
|
|||||||
|
|
||||||
layout (location = 0) out vec4 outFragColor;
|
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 poissonDisk[16] = vec2[](
|
||||||
vec2( -0.94201624, -0.39906216 ),
|
vec2( -0.94201624, -0.39906216 ),
|
||||||
vec2( 0.94558609, -0.76890725 ),
|
vec2( 0.94558609, -0.76890725 ),
|
||||||
@ -98,22 +108,6 @@ vec2 poissonDisk[16] = vec2[](
|
|||||||
vec2( 0.14383161, -0.14100790 )
|
vec2( 0.14383161, -0.14100790 )
|
||||||
);
|
);
|
||||||
|
|
||||||
struct Light {
|
|
||||||
vec3 position;
|
|
||||||
float radius;
|
|
||||||
|
|
||||||
vec3 color;
|
|
||||||
float power;
|
|
||||||
|
|
||||||
int type;
|
|
||||||
float depthBias;
|
|
||||||
float padding1;
|
|
||||||
float padding2;
|
|
||||||
|
|
||||||
mat4 view;
|
|
||||||
mat4 projection;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Matrices {
|
struct Matrices {
|
||||||
mat4 view[2];
|
mat4 view[2];
|
||||||
mat4 projection[2];
|
mat4 projection[2];
|
||||||
@ -150,11 +144,17 @@ struct Mode {
|
|||||||
|
|
||||||
layout (binding = 0) uniform UBO {
|
layout (binding = 0) uniform UBO {
|
||||||
Matrices matrices;
|
Matrices matrices;
|
||||||
vec3 ambient;
|
|
||||||
float kexp;
|
|
||||||
Mode mode;
|
Mode mode;
|
||||||
Fog fog;
|
Fog fog;
|
||||||
Light lights[LIGHTS];
|
|
||||||
|
uint lights;
|
||||||
|
uint materials;
|
||||||
|
uint textures;
|
||||||
|
uint drawCalls;
|
||||||
|
|
||||||
|
vec3 ambient;
|
||||||
|
float kexp;
|
||||||
} ubo;
|
} ubo;
|
||||||
|
|
||||||
void phong( Light light, vec4 albedoSpecular, inout vec3 i ) {
|
void phong( Light light, vec4 albedoSpecular, inout vec3 i ) {
|
||||||
@ -233,9 +233,7 @@ float random(vec3 seed, int i){
|
|||||||
}
|
}
|
||||||
|
|
||||||
float shadowFactor( Light light, uint shadowMap ) {
|
float shadowFactor( Light light, uint shadowMap ) {
|
||||||
vec3 point = position.world;
|
vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0);
|
||||||
|
|
||||||
vec4 positionClip = light.projection * light.view * vec4(point, 1.0);
|
|
||||||
positionClip.xyz /= positionClip.w;
|
positionClip.xyz /= positionClip.w;
|
||||||
|
|
||||||
if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0;
|
if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0;
|
||||||
@ -245,12 +243,12 @@ float shadowFactor( Light light, uint shadowMap ) {
|
|||||||
float factor = 1.0;
|
float factor = 1.0;
|
||||||
|
|
||||||
// spot light
|
// spot light
|
||||||
if ( light.type == -2 || light.type == -3 ) {
|
if ( light.type == 2 || light.type == 3 ) {
|
||||||
float dist = length( positionClip.xy );
|
float dist = length( positionClip.xy );
|
||||||
if ( dist > 0.5 ) return 0.0;
|
if ( dist > 0.5 ) return 0.0;
|
||||||
|
|
||||||
// spot light with attenuation
|
// spot light with attenuation
|
||||||
if ( light.type == -3 ) {
|
if ( light.type == 3 ) {
|
||||||
factor = 1.0 - (pow(dist * 2,2.0));
|
factor = 1.0 - (pow(dist * 2,2.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -267,15 +265,16 @@ float shadowFactor( Light light, uint shadowMap ) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
float eyeDepth = positionClip.z;
|
float eyeDepth = positionClip.z;
|
||||||
int samples = poissonDisk.length();
|
|
||||||
|
int samples = POISSON_DISK;
|
||||||
if ( samples <= 1 ) {
|
if ( samples <= 1 ) {
|
||||||
return eyeDepth < texture(samplerShadows[shadowMap], uv).r - bias ? 0.0 : factor;
|
return eyeDepth < texture(samplerTextures[shadowMap], uv).r - bias ? 0.0 : factor;
|
||||||
}
|
}
|
||||||
for ( int i = 0; i < samples; ++i ) {
|
for ( int i = 0; i < samples; ++i ) {
|
||||||
// int index = i;
|
// int index = i;
|
||||||
// int index = int( float(samples) * random(gl_FragCoord.xyy, i) ) % samples;
|
// 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;
|
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;
|
float lightDepth = texture(samplerTextures[shadowMap], uv + poissonDisk[index] / 700.0 ).r;
|
||||||
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
|
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
|
||||||
}
|
}
|
||||||
return factor;
|
return factor;
|
||||||
@ -498,6 +497,7 @@ void fog( inout vec3 i, float scale ) {
|
|||||||
if ( ubo.fog.stepScale <= 0 ) return;
|
if ( ubo.fog.stepScale <= 0 ) return;
|
||||||
if ( ubo.fog.range.x == 0 || ubo.fog.range.y == 0 ) return;
|
if ( ubo.fog.range.x == 0 || ubo.fog.range.y == 0 ) return;
|
||||||
|
|
||||||
|
#if RAY_MARCH_FOG
|
||||||
mat4 iProjView = inverse( ubo.matrices.projection[inPushConstantPass] * ubo.matrices.view[inPushConstantPass] );
|
mat4 iProjView = inverse( ubo.matrices.projection[inPushConstantPass] * ubo.matrices.view[inPushConstantPass] );
|
||||||
vec4 near4 = iProjView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
|
vec4 near4 = iProjView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
|
||||||
vec4 far4 = iProjView * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
|
vec4 far4 = iProjView * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
|
||||||
@ -536,6 +536,7 @@ void fog( inout vec3 i, float scale ) {
|
|||||||
}
|
}
|
||||||
i.rgb = mix(ubo.fog.color.rgb, i.rgb, transmittance);
|
i.rgb = mix(ubo.fog.color.rgb, i.rgb, transmittance);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
vec3 color = ubo.fog.color.rgb;
|
vec3 color = ubo.fog.color.rgb;
|
||||||
float inner = ubo.fog.range.x;
|
float inner = ubo.fog.range.x;
|
||||||
@ -556,21 +557,14 @@ vec3 decodeNormals( vec2 enc ) {
|
|||||||
n.z = 1-f/2;
|
n.z = 1-f/2;
|
||||||
return normalize(n);
|
return normalize(n);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
vec4 sampleTexture( uint drawId, int textureIndex, vec2 uv, vec4 base ) {
|
|
||||||
if ( TEXTURES <= textureIndex || textureIndex < 0 ) return base;
|
|
||||||
Texture t = textures[textureIndex+1];
|
|
||||||
return texture( samplerTextures[drawId], mix( t.lerp.xy, t.lerp.zw, uv ) );
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool validTextureIndex( int textureIndex ) {
|
bool validTextureIndex( int textureIndex ) {
|
||||||
return 0 <= textureIndex && textureIndex < TEXTURES;
|
return 0 <= textureIndex && textureIndex < ubo.textures;
|
||||||
}
|
}
|
||||||
vec4 sampleTexture( uint drawId, int textureIndex, vec2 uv, vec4 base ) {
|
vec4 sampleTexture( uint drawId, int textureIndex, vec2 uv, vec4 base ) {
|
||||||
if ( !validTextureIndex( textureIndex ) ) return base;
|
if ( !validTextureIndex( textureIndex ) ) return base;
|
||||||
Texture t = textures[textureIndex+1];
|
Texture t = textures[textureIndex+1];
|
||||||
// if ( 0 <= t.remap && t.remap <= TEXTURES && t.remap != textureIndex ) t = textures[t.remap+1];
|
// if ( t.remap != textureIndex && validTextureIndex(t.remap) ) t = textures[t.remap+1];
|
||||||
return texture( samplerTextures[drawId], mix( t.lerp.xy, t.lerp.zw, uv ) );
|
return texture( samplerTextures[drawId], mix( t.lerp.xy, t.lerp.zw, uv ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,7 +589,7 @@ void main() {
|
|||||||
uint drawId = ID.x;
|
uint drawId = ID.x;
|
||||||
|
|
||||||
DrawCall drawCall = drawCalls[drawId];
|
DrawCall drawCall = drawCalls[drawId];
|
||||||
uint materialId = ID.y + 1;
|
uint materialId = ID.y;
|
||||||
materialId += drawCall.materialIndex;
|
materialId += drawCall.materialIndex;
|
||||||
|
|
||||||
Material material = materials[materialId];
|
Material material = materials[materialId];
|
||||||
@ -609,26 +603,29 @@ void main() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
float M = material.factorMetallic;
|
float M = material.factorMetallic;
|
||||||
float R = 0.5; //material.factorRoughness;
|
float R = material.factorRoughness * 4.0;
|
||||||
float AO = material.factorOcclusion;
|
float AO = material.factorOcclusion;
|
||||||
|
|
||||||
bool usePbr = true;
|
bool usePbr = true;
|
||||||
bool gammaCorrect = false;
|
bool gammaCorrect = false;
|
||||||
float litFactor = 1.0;
|
float litFactor = 1.0;
|
||||||
vec3 fragColor = C.rgb * ubo.ambient.rgb * AO;
|
vec3 fragColor = C.rgb * ubo.ambient.rgb * AO;
|
||||||
for ( uint i = 0; i < LIGHTS; ++i ) {
|
for ( uint i = 0; i < ubo.lights; ++i ) {
|
||||||
Light light = ubo.lights[i];
|
Light light = lights[i];
|
||||||
|
|
||||||
if ( light.power <= 0.001 ) continue;
|
if ( light.power <= 0.001 ) continue;
|
||||||
|
|
||||||
vec3 lightPositionWorld = light.position.xyz;
|
vec3 lightPositionWorld = light.position.xyz;
|
||||||
light.position.xyz = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position.xyz, 1));
|
light.position.xyz = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position.xyz, 1));
|
||||||
if ( light.type < 0 ) {
|
|
||||||
float factor = shadowFactor( light, i );
|
if ( 0 <= light.mapIndex && light.mapIndex < TEXTURES ) {
|
||||||
if ( factor <= 0.0001 ) continue;
|
float factor = shadowFactor( light, light.mapIndex );
|
||||||
|
// if ( factor <= 0.0001 ) continue;
|
||||||
light.power *= factor;
|
light.power *= factor;
|
||||||
litFactor += light.power;
|
litFactor += light.power;
|
||||||
}
|
}
|
||||||
if ( light.power <= 0.0001 ) continue;
|
if ( light.power <= 0.0001 ) continue;
|
||||||
|
|
||||||
if ( usePbr ) {
|
if ( usePbr ) {
|
||||||
pbr( light, C.rgb, M, R, lightPositionWorld, fragColor );
|
pbr( light, C.rgb, M, R, lightPositionWorld, fragColor );
|
||||||
} else
|
} else
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
#define UF_DEFERRED_SAMPLING 0
|
#define UF_DEFERRED_SAMPLING 1
|
||||||
|
#define UF_CAN_DISCARD 1
|
||||||
|
|
||||||
layout (constant_id = 0) const uint TEXTURES = 1;
|
layout (constant_id = 0) const uint TEXTURES = 1;
|
||||||
layout (binding = 0) uniform sampler2D samplerTextures[TEXTURES];
|
layout (binding = 0) uniform sampler2D samplerTextures[TEXTURES];
|
||||||
@ -72,18 +73,19 @@ vec4 sampleTexture( int textureIndex, vec2 uv, vec4 base ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
#if UF_DEFERRED_SAMPLING
|
vec4 C = vec4(0, 0, 0, 0);
|
||||||
|
vec3 P = inPosition;
|
||||||
vec3 N = inNormal;
|
vec3 N = inNormal;
|
||||||
|
#if UF_DEFERRED_SAMPLING
|
||||||
outUvs = fract(inUv);
|
outUvs = fract(inUv);
|
||||||
#else
|
vec4 outAlbedo = vec4(0,0,0,0);
|
||||||
|
#endif
|
||||||
|
#if !UF_DEFERRED_SAMPLING || UF_CAN_DISCARD
|
||||||
int materialId = int(inId.y);
|
int materialId = int(inId.y);
|
||||||
Material material = materials[materialId];
|
Material material = materials[materialId];
|
||||||
|
|
||||||
vec2 uv = fract(inUv.xy);
|
vec2 uv = fract(inUv.xy);
|
||||||
|
|
||||||
vec4 C = vec4(0, 0, 0, 0);
|
|
||||||
vec3 N = inNormal;
|
|
||||||
vec3 P = inPosition;
|
|
||||||
float M = material.factorMetallic;
|
float M = material.factorMetallic;
|
||||||
float R = material.factorRoughness;
|
float R = material.factorRoughness;
|
||||||
float AO = material.factorOcclusion;
|
float AO = material.factorOcclusion;
|
||||||
@ -96,8 +98,11 @@ void main() {
|
|||||||
{
|
{
|
||||||
Texture t = textures[material.indexAlbedo + 1];
|
Texture t = textures[material.indexAlbedo + 1];
|
||||||
C = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) );
|
C = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) );
|
||||||
|
if ( C.a < abs(material.factorAlphaCutoff) ) discard;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !UF_DEFERRED_SAMPLING
|
||||||
// sample normal
|
// sample normal
|
||||||
if ( validTextureIndex( material.indexNormal ) ) {
|
if ( validTextureIndex( material.indexNormal ) ) {
|
||||||
Texture t = textures[material.indexNormal + 1];
|
Texture t = textures[material.indexNormal + 1];
|
||||||
@ -120,14 +125,10 @@ void main() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( C.a < abs(material.factorAlphaCutoff) ) {
|
C.rgb *= inColor.rgb * C.a;
|
||||||
// outTransparency = C;
|
outAlbedo = vec4(C.rgb,1);
|
||||||
discard;
|
|
||||||
} else {
|
|
||||||
C.rgb *= inColor.rgb * C.a;
|
|
||||||
outAlbedo = vec4(C.rgb,1);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
outNormals = encodeNormals( N );
|
outNormals = encodeNormals( N );
|
||||||
outId = ivec2(inId.w, inId.y);
|
outId = ivec2(inId.w, inId.y);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,18 @@ namespace pod {
|
|||||||
uf::renderer::Texture2D texture;
|
uf::renderer::Texture2D texture;
|
||||||
};
|
};
|
||||||
struct UF_API Light {
|
struct UF_API Light {
|
||||||
|
struct UF_API Storage {
|
||||||
|
alignas(16) pod::Vector4f position;
|
||||||
|
alignas(16) pod::Vector4f color;
|
||||||
|
|
||||||
|
alignas(4) int32_t type = 0;
|
||||||
|
alignas(4) int32_t mapIndex = -1;
|
||||||
|
alignas(4) float depthBias = 0;
|
||||||
|
alignas(4) float padding = 0;
|
||||||
|
|
||||||
|
alignas(16) pod::Matrix4f view;
|
||||||
|
alignas(16) pod::Matrix4f projection;
|
||||||
|
};
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
pod::Transform<> transform = {};
|
pod::Transform<> transform = {};
|
||||||
pod::Vector3f color = { 1, 1, 1 };
|
pod::Vector3f color = { 1, 1, 1 };
|
||||||
|
@ -47,15 +47,15 @@ namespace {
|
|||||||
if ( graph.mode & ext::gltf::LoadMode::LOAD ) {
|
if ( graph.mode & ext::gltf::LoadMode::LOAD ) {
|
||||||
if ( graph.mode & ext::gltf::LoadMode::SEPARATE ) {
|
if ( graph.mode & ext::gltf::LoadMode::SEPARATE ) {
|
||||||
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
|
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
|
||||||
graphic.material.attachShader("./data/shaders/gltf.stereo.skinned.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
graphic.material.attachShader("./data/shaders/gltf.skinned.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||||
} else {
|
} else {
|
||||||
graphic.material.attachShader("./data/shaders/gltf.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
graphic.material.attachShader("./data/shaders/gltf.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
|
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
|
||||||
graphic.material.attachShader("./data/shaders/gltf.stereo.skinned.instanced.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
graphic.material.attachShader("./data/shaders/gltf.skinned.instanced.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||||
} else {
|
} else {
|
||||||
graphic.material.attachShader("./data/shaders/gltf.stereo.instanced.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
graphic.material.attachShader("./data/shaders/gltf.instanced.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
graphic.material.attachShader("./data/shaders/gltf.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
graphic.material.attachShader("./data/shaders/gltf.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
|
@ -216,8 +216,8 @@ void ext::vulkan::Buffers::updateBuffer( void* data, VkDeviceSize length, Buffer
|
|||||||
if ( !true ) {
|
if ( !true ) {
|
||||||
VK_VALIDATION_MESSAGE("Mismatch buffer update: Requesting " << buffer.allocationInfo.size << ", got " << length << "; Userdata might've been corrupted, please try validating with shader.validate() before updating buffer");
|
VK_VALIDATION_MESSAGE("Mismatch buffer update: Requesting " << buffer.allocationInfo.size << ", got " << length << "; Userdata might've been corrupted, please try validating with shader.validate() before updating buffer");
|
||||||
} else {
|
} else {
|
||||||
length = buffer.allocationInfo.size;
|
|
||||||
VK_VALIDATION_MESSAGE("Mismatch buffer update: Requesting " << buffer.allocationInfo.size << ", got " << length << ", resetting for safety");
|
VK_VALIDATION_MESSAGE("Mismatch buffer update: Requesting " << buffer.allocationInfo.size << ", got " << length << ", resetting for safety");
|
||||||
|
length = buffer.allocationInfo.size;
|
||||||
}
|
}
|
||||||
// assert(buffer.allocationInfo.size > length);
|
// assert(buffer.allocationInfo.size > length);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,9 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
|
#define VK_DEBUG_VALIDATION_MESSAGE(x)\
|
||||||
|
//VK_VALIDATION_MESSAGE(x);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
uint32_t VERTEX_BUFFER_BIND_ID = 0;
|
uint32_t VERTEX_BUFFER_BIND_ID = 0;
|
||||||
}
|
}
|
||||||
@ -450,16 +453,16 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
|
|||||||
size_t size = comp.get_declared_struct_size(base_type);
|
size_t size = comp.get_declared_struct_size(base_type);
|
||||||
if ( size <= 0 ) break;
|
if ( size <= 0 ) break;
|
||||||
if ( size > device.properties.limits.maxUniformBufferRange ) {
|
if ( size > device.properties.limits.maxUniformBufferRange ) {
|
||||||
//VK_VALIDATION_MESSAGE("Invalid uniform buffer length of " << size << " for shader " << filename);
|
VK_DEBUG_VALIDATION_MESSAGE("Invalid uniform buffer length of " << size << " for shader " << filename);
|
||||||
size = device.properties.limits.maxUniformBufferRange;
|
size = device.properties.limits.maxUniformBufferRange;
|
||||||
}
|
}
|
||||||
size_t misalignment = size % device.properties.limits.minStorageBufferOffsetAlignment;
|
size_t misalignment = size % device.properties.limits.minStorageBufferOffsetAlignment;
|
||||||
if ( misalignment != 0 ) {
|
if ( misalignment != 0 ) {
|
||||||
//VK_VALIDATION_MESSAGE("Invalid uniform buffer alignment of " << misalignment << " for shader " << filename << ", correcting...");
|
VK_DEBUG_VALIDATION_MESSAGE("Invalid uniform buffer alignment of " << misalignment << " for shader " << filename << ", correcting...");
|
||||||
size += misalignment;
|
size += misalignment;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
//VK_VALIDATION_MESSAGE("Uniform size of " << size << " for shader " << filename);
|
VK_DEBUG_VALIDATION_MESSAGE("Uniform size of " << size << " for shader " << filename);
|
||||||
auto& uniform = uniforms.emplace_back();
|
auto& uniform = uniforms.emplace_back();
|
||||||
uniform.create( size );
|
uniform.create( size );
|
||||||
}
|
}
|
||||||
@ -519,16 +522,16 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
|
|||||||
if ( size <= 0 ) continue;
|
if ( size <= 0 ) continue;
|
||||||
// not a multiple of 4, for some reason
|
// not a multiple of 4, for some reason
|
||||||
if ( size % 4 != 0 ) {
|
if ( size % 4 != 0 ) {
|
||||||
//VK_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename << ", must be multiple of 4, correcting...");
|
VK_DEBUG_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename << ", must be multiple of 4, correcting...");
|
||||||
size /= 4;
|
size /= 4;
|
||||||
++size;
|
++size;
|
||||||
size *= 4;
|
size *= 4;
|
||||||
}
|
}
|
||||||
if ( size > device.properties.limits.maxPushConstantsSize ) {
|
if ( size > device.properties.limits.maxPushConstantsSize ) {
|
||||||
//VK_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename);
|
VK_DEBUG_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename);
|
||||||
size = device.properties.limits.maxPushConstantsSize;
|
size = device.properties.limits.maxPushConstantsSize;
|
||||||
}
|
}
|
||||||
//VK_VALIDATION_MESSAGE("Push constant size of " << size << " for shader " << filename);
|
VK_DEBUG_VALIDATION_MESSAGE("Push constant size of " << size << " for shader " << filename);
|
||||||
{
|
{
|
||||||
auto& pushConstant = pushConstants.emplace_back();
|
auto& pushConstant = pushConstants.emplace_back();
|
||||||
pushConstant.create( size );
|
pushConstant.create( size );
|
||||||
@ -557,7 +560,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
|
|||||||
}
|
}
|
||||||
if ( specializationSize > 0 ) {
|
if ( specializationSize > 0 ) {
|
||||||
specializationConstants.create( specializationSize );
|
specializationConstants.create( specializationSize );
|
||||||
//VK_VALIDATION_MESSAGE("Specialization constants size of " << specializationSize << " for shader " << filename);
|
VK_DEBUG_VALIDATION_MESSAGE("Specialization constants size of " << specializationSize << " for shader " << filename);
|
||||||
|
|
||||||
uint8_t* s = (uint8_t*) (void*) specializationConstants;
|
uint8_t* s = (uint8_t*) (void*) specializationConstants;
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
@ -599,13 +602,13 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
|
|||||||
memcpy( &buffer[0], &v, sizeof(v) );
|
memcpy( &buffer[0], &v, sizeof(v) );
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
//VK_VALIDATION_MESSAGE("Unregistered specialization constant type at offset " << offset << " for shader " << filename );
|
VK_DEBUG_VALIDATION_MESSAGE("Unregistered specialization constant type at offset " << offset << " for shader " << filename );
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
member["name"] = name;
|
member["name"] = name;
|
||||||
member["size"] = size;
|
member["size"] = size;
|
||||||
member["default"] = member["value"];
|
member["default"] = member["value"];
|
||||||
//VK_VALIDATION_MESSAGE("Specialization constant: " << member["type"].as<std::string>() << " " << name << " = " << member["value"].dump() << "; at offset " << offset << " for shader " << filename );
|
VK_DEBUG_VALIDATION_MESSAGE("Specialization constant: " << member["type"].as<std::string>() << " " << name << " = " << member["value"].dump() << "; at offset " << offset << " for shader " << filename );
|
||||||
metadata["specializationConstants"].emplace_back(member);
|
metadata["specializationConstants"].emplace_back(member);
|
||||||
|
|
||||||
memcpy( &s[offset], &buffer, size );
|
memcpy( &s[offset], &buffer, size );
|
||||||
@ -675,7 +678,7 @@ bool ext::vulkan::Shader::validate() {
|
|||||||
if ( it == uniforms.end() ) break;
|
if ( it == uniforms.end() ) break;
|
||||||
auto& uniform = *(it++);
|
auto& uniform = *(it++);
|
||||||
if ( uniform.data().len != buffer.allocationInfo.size ) {
|
if ( uniform.data().len != buffer.allocationInfo.size ) {
|
||||||
//VK_VALIDATION_MESSAGE("Uniform size mismatch: Expected " << buffer.allocationInfo.size << ", got " << uniform.data().len << "; fixing...");
|
VK_DEBUG_VALIDATION_MESSAGE("Uniform size mismatch: Expected " << buffer.allocationInfo.size << ", got " << uniform.data().len << "; fixing...");
|
||||||
uniform.destroy();
|
uniform.destroy();
|
||||||
uniform.create(buffer.allocationInfo.size);
|
uniform.create(buffer.allocationInfo.size);
|
||||||
valid = false;
|
valid = false;
|
||||||
@ -795,7 +798,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
|
|||||||
for ( auto& pushConstant : shader.pushConstants ) {
|
for ( auto& pushConstant : shader.pushConstants ) {
|
||||||
size_t len = pushConstant.data().len;
|
size_t len = pushConstant.data().len;
|
||||||
if ( len <= 0 || len > device.properties.limits.maxPushConstantsSize ) {
|
if ( len <= 0 || len > device.properties.limits.maxPushConstantsSize ) {
|
||||||
//VK_VALIDATION_MESSAGE("Invalid push constant length of " << len << " for shader " << shader.filename);
|
VK_DEBUG_VALIDATION_MESSAGE("Invalid push constant length of " << len << " for shader " << shader.filename);
|
||||||
// goto PIPELINE_INITIALIZATION_INVALID;
|
// goto PIPELINE_INITIALIZATION_INVALID;
|
||||||
len = device.properties.limits.maxPushConstantsSize;
|
len = device.properties.limits.maxPushConstantsSize;
|
||||||
}
|
}
|
||||||
@ -993,7 +996,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
|
|||||||
int32_t& v = ((int32_t*) s)[i];
|
int32_t& v = ((int32_t*) s)[i];
|
||||||
// failsafe, because for some reason things break
|
// failsafe, because for some reason things break
|
||||||
if ( payload["validate"].as<bool>() && v == 0 ) {
|
if ( payload["validate"].as<bool>() && v == 0 ) {
|
||||||
//VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`");
|
VK_DEBUG_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`");
|
||||||
v = payload["value"].is<int32_t>() ? payload["value"].as<int32_t>() : payload["default"].as<int32_t>();
|
v = payload["value"].is<int32_t>() ? payload["value"].as<int32_t>() : payload["default"].as<int32_t>();
|
||||||
}
|
}
|
||||||
payload["value"] = v;
|
payload["value"] = v;
|
||||||
@ -1001,7 +1004,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
|
|||||||
uint32_t& v = ((uint32_t*) s)[i];
|
uint32_t& v = ((uint32_t*) s)[i];
|
||||||
// failsafe, because for some reason things break
|
// failsafe, because for some reason things break
|
||||||
if ( payload["validate"].as<bool>() && v == 0 ) {
|
if ( payload["validate"].as<bool>() && v == 0 ) {
|
||||||
//VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`");
|
VK_DEBUG_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`");
|
||||||
v = payload["value"].is<uint32_t>() ? payload["value"].as<uint32_t>() : payload["default"].as<uint32_t>();
|
v = payload["value"].is<uint32_t>() ? payload["value"].as<uint32_t>() : payload["default"].as<uint32_t>();
|
||||||
}
|
}
|
||||||
payload["value"] = v;
|
payload["value"] = v;
|
||||||
@ -1009,13 +1012,13 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
|
|||||||
float& v = ((float*) s)[i];
|
float& v = ((float*) s)[i];
|
||||||
// failsafe, because for some reason things break
|
// failsafe, because for some reason things break
|
||||||
if ( payload["validate"].as<bool>() && v == 0 ) {
|
if ( payload["validate"].as<bool>() && v == 0 ) {
|
||||||
//VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`");
|
VK_DEBUG_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`");
|
||||||
v = payload["value"].is<float>() ? payload["value"].as<float>() : payload["default"].as<float>();
|
v = payload["value"].is<float>() ? payload["value"].as<float>() : payload["default"].as<float>();
|
||||||
}
|
}
|
||||||
payload["value"] = v;
|
payload["value"] = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//VK_VALIDATION_MESSAGE("Specialization constants for shader `" << shader.filename << "`: " << shader.metadata["specializationConstants"].dump(1, '\t'));
|
VK_DEBUG_VALIDATION_MESSAGE("Specialization constants for shader `" << shader.filename << "`: " << shader.metadata["specializationConstants"].dump(1, '\t'));
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -1047,14 +1050,14 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
|
|||||||
pipelineCreateInfo.subpass = descriptor.subpass;
|
pipelineCreateInfo.subpass = descriptor.subpass;
|
||||||
|
|
||||||
VK_CHECK_RESULT(vkCreateGraphicsPipelines( device, device.pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline));
|
VK_CHECK_RESULT(vkCreateGraphicsPipelines( device, device.pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline));
|
||||||
//VK_VALIDATION_MESSAGE("Created graphics pipeline");
|
VK_DEBUG_VALIDATION_MESSAGE("Created graphics pipeline");
|
||||||
}
|
}
|
||||||
|
|
||||||
graphic.process = true;
|
graphic.process = true;
|
||||||
return;
|
return;
|
||||||
PIPELINE_INITIALIZATION_INVALID:
|
PIPELINE_INITIALIZATION_INVALID:
|
||||||
graphic.process = false;
|
graphic.process = false;
|
||||||
//VK_VALIDATION_MESSAGE("Pipeline initialization invalid, updating next tick...");
|
VK_DEBUG_VALIDATION_MESSAGE("Pipeline initialization invalid, updating next tick...");
|
||||||
uf::thread::add( uf::thread::get("Main"), [&]() -> int {
|
uf::thread::add( uf::thread::get("Main"), [&]() -> int {
|
||||||
this->initialize( graphic, descriptor );
|
this->initialize( graphic, descriptor );
|
||||||
return 0;}, true );
|
return 0;}, true );
|
||||||
@ -1255,18 +1258,23 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip
|
|||||||
for ( size_t i = 0; i < descriptor.descriptorCount; ++i ) {
|
for ( size_t i = 0; i < descriptor.descriptorCount; ++i ) {
|
||||||
if ( descriptor.pBufferInfo ) {
|
if ( descriptor.pBufferInfo ) {
|
||||||
if ( descriptor.pBufferInfo[i].offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) {
|
if ( descriptor.pBufferInfo[i].offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) {
|
||||||
//VK_VALIDATION_MESSAGE("Invalid descriptor for buffer: " << descriptor.pBufferInfo[i].buffer << " (Offset: " << descriptor.pBufferInfo[i].offset << ", Range: " << descriptor.pBufferInfo[i].range << "), invalidating...");
|
VK_DEBUG_VALIDATION_MESSAGE("Invalid descriptor for buffer: " << descriptor.pBufferInfo[i].buffer << " (Offset: " << descriptor.pBufferInfo[i].offset << ", Range: " << descriptor.pBufferInfo[i].range << "), invalidating...");
|
||||||
goto PIPELINE_UPDATE_INVALID;
|
goto PIPELINE_UPDATE_INVALID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( descriptor.pImageInfo ) {
|
if ( descriptor.pImageInfo ) {
|
||||||
|
if ( descriptor.pImageInfo[i].imageView == 0x0 ) {
|
||||||
|
VK_DEBUG_VALIDATION_MESSAGE("Null image view, replacing with fallback texture...");
|
||||||
|
auto pointer = const_cast<VkDescriptorImageInfo*>(&descriptor.pImageInfo[i]);
|
||||||
|
*pointer = emptyTexture.descriptor;
|
||||||
|
}
|
||||||
if ( descriptor.pImageInfo[i].imageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ) {
|
if ( descriptor.pImageInfo[i].imageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ) {
|
||||||
//VK_VALIDATION_MESSAGE("Image layout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, fixing to VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL");
|
VK_DEBUG_VALIDATION_MESSAGE("Image layout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, fixing to VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL");
|
||||||
auto pointer = const_cast<VkDescriptorImageInfo*>(&descriptor.pImageInfo[i]);
|
auto pointer = const_cast<VkDescriptorImageInfo*>(&descriptor.pImageInfo[i]);
|
||||||
pointer->imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
pointer->imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
||||||
}
|
}
|
||||||
if ( descriptor.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER && !descriptor.pImageInfo[i].sampler ) {
|
if ( descriptor.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER && !descriptor.pImageInfo[i].sampler ) {
|
||||||
//VK_VALIDATION_MESSAGE("Image descriptor type is VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, yet lacks a sampler, adding default sampler...");
|
VK_DEBUG_VALIDATION_MESSAGE("Image descriptor type is VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, yet lacks a sampler, adding default sampler...");
|
||||||
auto pointer = const_cast<VkDescriptorImageInfo*>(&descriptor.pImageInfo[i]);
|
auto pointer = const_cast<VkDescriptorImageInfo*>(&descriptor.pImageInfo[i]);
|
||||||
pointer->sampler = emptyTexture.sampler.sampler;
|
pointer->sampler = emptyTexture.sampler.sampler;
|
||||||
}
|
}
|
||||||
@ -1287,7 +1295,7 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip
|
|||||||
|
|
||||||
PIPELINE_UPDATE_INVALID:
|
PIPELINE_UPDATE_INVALID:
|
||||||
graphic.process = false;
|
graphic.process = false;
|
||||||
//VK_VALIDATION_MESSAGE("Pipeline update invalid, updating next tick...");
|
VK_DEBUG_VALIDATION_MESSAGE("Pipeline update invalid, updating next tick...");
|
||||||
uf::thread::add( uf::thread::get("Main"), [&]() -> int {
|
uf::thread::add( uf::thread::get("Main"), [&]() -> int {
|
||||||
this->update( graphic, descriptor );
|
this->update( graphic, descriptor );
|
||||||
return 0;}, true );
|
return 0;}, true );
|
||||||
@ -1435,13 +1443,13 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, size_t pass, s
|
|||||||
void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, GraphicDescriptor& descriptor, size_t pass, size_t draw ) {
|
void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, GraphicDescriptor& descriptor, size_t pass, size_t draw ) {
|
||||||
if ( !process ) return;
|
if ( !process ) return;
|
||||||
if ( !this->hasPipeline( descriptor ) ) {
|
if ( !this->hasPipeline( descriptor ) ) {
|
||||||
//VK_VALIDATION_MESSAGE(this << ": has no valid pipeline");
|
VK_DEBUG_VALIDATION_MESSAGE(this << ": has no valid pipeline");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& pipeline = this->getPipeline( descriptor );
|
auto& pipeline = this->getPipeline( descriptor );
|
||||||
if ( pipeline.descriptorSet == VK_NULL_HANDLE ) {
|
if ( pipeline.descriptorSet == VK_NULL_HANDLE ) {
|
||||||
//VK_VALIDATION_MESSAGE(this << ": has no valid pipeline descriptor set");
|
VK_DEBUG_VALIDATION_MESSAGE(this << ": has no valid pipeline descriptor set");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,24 +283,31 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
|||||||
|
|
||||||
auto& shader = blitter.material.shaders.back();
|
auto& shader = blitter.material.shaders.back();
|
||||||
struct SpecializationConstant {
|
struct SpecializationConstant {
|
||||||
uint32_t maxLights = 256;
|
uint32_t maxTextures = 512;
|
||||||
uint32_t maxTextures = 256;
|
|
||||||
};
|
};
|
||||||
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
|
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
|
||||||
|
|
||||||
auto& metadata = scene.getComponent<uf::Serializer>();
|
auto& metadata = scene.getComponent<uf::Serializer>();
|
||||||
specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>();
|
size_t maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>();
|
||||||
specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>();
|
specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>();
|
||||||
for ( auto& binding : shader.descriptorSetLayoutBindings ) {
|
for ( auto& binding : shader.descriptorSetLayoutBindings ) {
|
||||||
if ( binding.descriptorCount > 1 )
|
if ( binding.descriptorCount > 1 )
|
||||||
binding.descriptorCount = specializationConstants.maxLights;
|
binding.descriptorCount = specializationConstants.maxTextures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<pod::Light::Storage> lights(maxLights);
|
||||||
std::vector<pod::Material::Storage> materials(specializationConstants.maxTextures);
|
std::vector<pod::Material::Storage> materials(specializationConstants.maxTextures);
|
||||||
std::vector<pod::Texture::Storage> textures(specializationConstants.maxTextures);
|
std::vector<pod::Texture::Storage> textures(specializationConstants.maxTextures);
|
||||||
std::vector<pod::DrawCall> drawCalls(specializationConstants.maxTextures);
|
std::vector<pod::DrawCall> drawCalls(specializationConstants.maxTextures);
|
||||||
|
|
||||||
for ( auto& material : materials ) material.colorBase = {0,0,0,0};
|
for ( auto& material : materials ) material.colorBase = {0,0,0,0};
|
||||||
|
|
||||||
|
this->metadata["lightBufferIndex"] = blitter.initializeBuffer(
|
||||||
|
(void*) lights.data(),
|
||||||
|
lights.size() * sizeof(pod::Light::Storage),
|
||||||
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||||
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||||
|
);
|
||||||
this->metadata["materialBufferIndex"] = blitter.initializeBuffer(
|
this->metadata["materialBufferIndex"] = blitter.initializeBuffer(
|
||||||
(void*) materials.data(),
|
(void*) materials.data(),
|
||||||
materials.size() * sizeof(pod::Material::Storage),
|
materials.size() * sizeof(pod::Material::Storage),
|
||||||
|
@ -169,41 +169,22 @@ void ext::LightBehavior::tick( uf::Object& self ) {
|
|||||||
// omni light
|
// omni light
|
||||||
if ( metadata["light"]["shadows"].as<bool>() && metadata["light"]["type"].as<std::string>() == "point" ) {
|
if ( metadata["light"]["shadows"].as<bool>() && metadata["light"]["type"].as<std::string>() == "point" ) {
|
||||||
auto transform = camera.getTransform();
|
auto transform = camera.getTransform();
|
||||||
/*
|
|
||||||
transform.orientation = uf::quaternion::axisAngle( { 0, 1, 0 }, 0 * 1.57079633 );
|
|
||||||
camera.setView( uf::matrix::inverse( uf::transform::model( transform, false ) ), 0 );
|
|
||||||
|
|
||||||
transform.orientation = uf::quaternion::axisAngle( { 0, 1, 0 }, 1 * 1.57079633 );
|
|
||||||
camera.setView( uf::matrix::inverse( uf::transform::model( transform, false ) ), 1 );
|
|
||||||
|
|
||||||
transform.orientation = uf::quaternion::axisAngle( { 0, 1, 0 }, 2 * 1.57079633 );
|
|
||||||
camera.setView( uf::matrix::inverse( uf::transform::model( transform, false ) ), 2 );
|
|
||||||
|
|
||||||
transform.orientation = uf::quaternion::axisAngle( { 0, 1, 0 }, 3 * 1.57079633 );
|
|
||||||
camera.setView( uf::matrix::inverse( uf::transform::model( transform, false ) ), 3 );
|
|
||||||
|
|
||||||
transform.orientation = uf::quaternion::axisAngle( { 1, 0, 0 }, 1 * 1.57079633 );
|
|
||||||
camera.setView( uf::matrix::inverse( uf::transform::model( transform, false ) ), 4 );
|
|
||||||
|
|
||||||
transform.orientation = uf::quaternion::axisAngle( { 1, 0, 0 }, 3 * 1.57079633 );
|
|
||||||
camera.setView( uf::matrix::inverse( uf::transform::model( transform, false ) ), 5 );
|
|
||||||
*/
|
|
||||||
std::vector<pod::Quaternion<>> rotations = {
|
std::vector<pod::Quaternion<>> rotations = {
|
||||||
|
/*
|
||||||
{0, 0, 0, 1},
|
{0, 0, 0, 1},
|
||||||
{0, 0.707107, 0, -0.707107},
|
{0, 0.707107, 0, -0.707107},
|
||||||
{0, 1, 0, 0},
|
{0, 1, 0, 0},
|
||||||
{0, 0.707107, 0, 0.707107},
|
{0, 0.707107, 0, 0.707107},
|
||||||
{-0.707107, 0, 0, -0.707107},
|
{-0.707107, 0, 0, -0.707107},
|
||||||
{0.707107, 0, 0, -0.707107},
|
{0.707107, 0, 0, -0.707107},
|
||||||
|
*/
|
||||||
/*
|
|
||||||
uf::quaternion::axisAngle( { 0, 1, 0 }, 0 * 1.57079633 ),
|
uf::quaternion::axisAngle( { 0, 1, 0 }, 0 * 1.57079633 ),
|
||||||
uf::quaternion::axisAngle( { 0, 1, 0 }, 1 * 1.57079633 ),
|
uf::quaternion::axisAngle( { 0, 1, 0 }, 1 * 1.57079633 ),
|
||||||
uf::quaternion::axisAngle( { 0, 1, 0 }, 2 * 1.57079633 ),
|
uf::quaternion::axisAngle( { 0, 1, 0 }, 2 * 1.57079633 ),
|
||||||
uf::quaternion::axisAngle( { 0, 1, 0 }, 3 * 1.57079633 ),
|
uf::quaternion::axisAngle( { 0, 1, 0 }, 3 * 1.57079633 ),
|
||||||
|
|
||||||
uf::quaternion::axisAngle( { 1, 0, 0 }, 1 * 1.57079633 ),
|
uf::quaternion::axisAngle( { 1, 0, 0 }, 1 * 1.57079633 ),
|
||||||
uf::quaternion::axisAngle( { 1, 0, 0 }, 3 * 1.57079633 ),
|
uf::quaternion::axisAngle( { 1, 0, 0 }, 3 * 1.57079633 ),
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
for ( size_t i = 0; i < rotations.size(); ++i ) {
|
for ( size_t i = 0; i < rotations.size(); ++i ) {
|
||||||
auto transform = camera.getTransform();
|
auto transform = camera.getTransform();
|
||||||
|
@ -168,6 +168,7 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
|
|||||||
float n = perlins[i];
|
float n = perlins[i];
|
||||||
n = n - floor(n);
|
n = n - floor(n);
|
||||||
float normalized = (n - low) / (high - low);
|
float normalized = (n - low) / (high - low);
|
||||||
|
if ( normalized >= 1.0f ) normalized = 1.0f;
|
||||||
pixels[i] = static_cast<uint8_t>(floor(normalized * 255));
|
pixels[i] = static_cast<uint8_t>(floor(normalized * 255));
|
||||||
}
|
}
|
||||||
texture.fromBuffers( (void*) pixels.data(), pixels.size(), VK_FORMAT_R8_UNORM, size.x, size.y, size.z, 1, ext::vulkan::device );
|
texture.fromBuffers( (void*) pixels.data(), pixels.size(), VK_FORMAT_R8_UNORM, size.x, size.y, size.z, 1, ext::vulkan::device );
|
||||||
@ -286,13 +287,14 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
|||||||
auto& controllerMetadata = controller.getComponent<uf::Serializer>();
|
auto& controllerMetadata = controller.getComponent<uf::Serializer>();
|
||||||
auto& controllerTransform = controller.getComponent<pod::Transform<>>();
|
auto& controllerTransform = controller.getComponent<pod::Transform<>>();
|
||||||
std::vector<uf::Graphic*> blitters = renderMode.getBlitters();
|
std::vector<uf::Graphic*> blitters = renderMode.getBlitters();
|
||||||
|
|
||||||
|
size_t maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>();
|
||||||
|
|
||||||
struct UniformDescriptor {
|
struct UniformDescriptor {
|
||||||
struct Matrices {
|
struct Matrices {
|
||||||
alignas(16) pod::Matrix4f view[2];
|
alignas(16) pod::Matrix4f view[2];
|
||||||
alignas(16) pod::Matrix4f projection[2];
|
alignas(16) pod::Matrix4f projection[2];
|
||||||
} matrices;
|
} matrices;
|
||||||
alignas(16) pod::Vector4f ambient;
|
|
||||||
struct Mode {
|
struct Mode {
|
||||||
alignas(8) pod::Vector2ui type;
|
alignas(8) pod::Vector2ui type;
|
||||||
alignas(8) pod::Vector2ui padding;
|
alignas(8) pod::Vector2ui padding;
|
||||||
@ -311,25 +313,18 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
|||||||
alignas(4) float padding2;
|
alignas(4) float padding2;
|
||||||
alignas(4) float padding3;
|
alignas(4) float padding3;
|
||||||
} fog;
|
} fog;
|
||||||
struct Light {
|
struct {
|
||||||
alignas(16) pod::Vector4f position;
|
alignas(4) uint32_t lights = 0;
|
||||||
alignas(16) pod::Vector4f color;
|
alignas(4) uint32_t materials = 0;
|
||||||
|
alignas(4) uint32_t textures = 0;
|
||||||
alignas(4) int32_t type = 0;
|
alignas(4) uint32_t drawCalls = 0;
|
||||||
alignas(4) float depthBias = 0;
|
} lengths;
|
||||||
alignas(4) float padding1 = 0;
|
alignas(16) pod::Vector4f ambient;
|
||||||
alignas(4) float padding2 = 0;
|
|
||||||
|
|
||||||
alignas(16) pod::Matrix4f view;
|
|
||||||
alignas(16) pod::Matrix4f projection;
|
|
||||||
} lights;
|
|
||||||
};
|
};
|
||||||
struct SpecializationConstant {
|
struct SpecializationConstant {
|
||||||
uint32_t maxLights = 256;
|
uint32_t maxTextures = 512;
|
||||||
uint32_t maxTextures = 256;
|
|
||||||
} specializationConstants;
|
} specializationConstants;
|
||||||
specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>();
|
specializationConstants.maxTextures = maxTextures;
|
||||||
specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>();
|
|
||||||
|
|
||||||
struct LightInfo {
|
struct LightInfo {
|
||||||
uf::Entity* entity = NULL;
|
uf::Entity* entity = NULL;
|
||||||
@ -406,7 +401,6 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
|||||||
uint8_t* buffer = (uint8_t*) (void*) uniform;
|
uint8_t* buffer = (uint8_t*) (void*) uniform;
|
||||||
|
|
||||||
UniformDescriptor* uniforms = (UniformDescriptor*) buffer;
|
UniformDescriptor* uniforms = (UniformDescriptor*) buffer;
|
||||||
UniformDescriptor::Light* lights = (UniformDescriptor::Light*) &buffer[sizeof(UniformDescriptor) - sizeof(UniformDescriptor::Light)];
|
|
||||||
|
|
||||||
for ( std::size_t i = 0; i < 2; ++i ) {
|
for ( std::size_t i = 0; i < 2; ++i ) {
|
||||||
uniforms->matrices.view[i] = camera.getView( i );
|
uniforms->matrices.view[i] = camera.getView( i );
|
||||||
@ -436,85 +430,61 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
|||||||
uniforms->mode.parameters.w = uf::physics::time::current;
|
uniforms->mode.parameters.w = uf::physics::time::current;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( size_t i = 0; i < specializationConstants.maxLights; ++i ) {
|
|
||||||
UniformDescriptor::Light& light = lights[i];
|
|
||||||
light = {};
|
|
||||||
light.position = { 0, 0, 0, 0 };
|
|
||||||
light.color = { 0, 0, 0, 0 };
|
|
||||||
light.type = 0;
|
|
||||||
light.depthBias = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<VkImage> previousTextures;
|
std::vector<VkImage> previousTextures;
|
||||||
for ( auto& texture : graphic.material.textures ) previousTextures.emplace_back(texture.image);
|
for ( auto& texture : graphic.material.textures ) previousTextures.emplace_back(texture.image);
|
||||||
|
|
||||||
graphic.material.textures.clear();
|
graphic.material.textures.clear();
|
||||||
// add noise texture
|
// add noise texture
|
||||||
graphic.material.textures.emplace_back().aliasTexture(this->getComponent<uf::renderer::Texture2D>());
|
graphic.material.textures.emplace_back().aliasTexture(this->getComponent<uf::renderer::Texture2D>());
|
||||||
|
|
||||||
|
size_t updateThreshold = metadata["system"]["config"]["engine"]["scenes"]["lights"]["update threshold"].as<size_t>();
|
||||||
|
size_t maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>();
|
||||||
|
size_t textureSlot = 0;
|
||||||
|
|
||||||
|
std::vector<pod::Light::Storage> lights;
|
||||||
|
lights.reserve( maxLights );
|
||||||
|
|
||||||
|
std::vector<pod::Material::Storage> materials;
|
||||||
|
materials.reserve(maxTextures);
|
||||||
|
materials.emplace_back().colorBase = {0,0,0,0};
|
||||||
|
|
||||||
|
std::vector<pod::Texture::Storage> textures;
|
||||||
|
textures.reserve(maxTextures);
|
||||||
|
|
||||||
|
std::vector<pod::DrawCall> drawCalls;
|
||||||
|
drawCalls.reserve(maxTextures);
|
||||||
|
|
||||||
// add materials
|
// add materials
|
||||||
{
|
{
|
||||||
size_t attachedTextures = 0;
|
|
||||||
std::vector<pod::Material::Storage> materials;
|
|
||||||
materials.reserve(specializationConstants.maxTextures);
|
|
||||||
|
|
||||||
std::vector<pod::Texture::Storage> textures;
|
|
||||||
textures.reserve(specializationConstants.maxTextures);
|
|
||||||
|
|
||||||
std::vector<pod::DrawCall> drawCalls;
|
|
||||||
drawCalls.reserve(specializationConstants.maxTextures);
|
|
||||||
|
|
||||||
materials.emplace_back().colorBase = {0,0,0,0};
|
|
||||||
|
|
||||||
for ( auto* entity : graphs ) {
|
for ( auto* entity : graphs ) {
|
||||||
auto& graph = *entity;
|
auto& graph = *entity;
|
||||||
|
|
||||||
|
drawCalls.emplace_back(pod::DrawCall{
|
||||||
|
materials.size(),
|
||||||
|
graph.materials.size(),
|
||||||
|
textures.size(),
|
||||||
|
graph.textures.size()
|
||||||
|
});
|
||||||
|
|
||||||
size_t startMaterial = materials.size() - 1;
|
for ( auto& material : graph.materials ) materials.emplace_back( material.storage );
|
||||||
size_t startTexture = textures.size();
|
for ( auto& texture : graph.textures ) textures.emplace_back( texture.storage );
|
||||||
|
|
||||||
{
|
|
||||||
auto& drawCall = drawCalls.emplace_back();
|
|
||||||
drawCall.materialIndex = startMaterial;
|
|
||||||
drawCall.textureIndex = startTexture;
|
|
||||||
|
|
||||||
drawCall.materials = graph.materials.size() - 1;
|
|
||||||
drawCall.textures = graph.textures.size();
|
|
||||||
}
|
|
||||||
for ( auto& material : graph.materials ) {
|
|
||||||
auto& m = materials.emplace_back( material.storage );
|
|
||||||
// m.indexAlbedo += startMaterial;
|
|
||||||
// m.indexNormal += startMaterial;
|
|
||||||
// m.indexEmissive += startMaterial;
|
|
||||||
// m.indexOcclusion += startMaterial;
|
|
||||||
// m.indexMetallicRoughness += startMaterial;
|
|
||||||
}
|
|
||||||
for ( auto& texture : graph.textures ) {
|
|
||||||
auto& t = textures.emplace_back( texture.storage );
|
|
||||||
// t.index += startTexture;
|
|
||||||
// t.remap += startTexture;
|
|
||||||
}
|
|
||||||
for ( auto& texture : graph.textures ) {
|
for ( auto& texture : graph.textures ) {
|
||||||
if ( !texture.texture.device ) continue;
|
if ( !texture.texture.device ) continue;
|
||||||
++attachedTextures;
|
|
||||||
graphic.material.textures.emplace_back().aliasTexture(texture.texture);
|
graphic.material.textures.emplace_back().aliasTexture(texture.texture);
|
||||||
|
++textureSlot;
|
||||||
|
|
||||||
if ( graph.atlas ) break;
|
if ( graph.atlas ) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while ( attachedTextures++ < specializationConstants.maxTextures ) {
|
|
||||||
graphic.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty);
|
uniforms->lengths.materials = std::min( materials.size(), maxTextures );
|
||||||
}
|
uniforms->lengths.textures = std::min( textures.size(), maxTextures );
|
||||||
|
uniforms->lengths.drawCalls = std::min( drawCalls.size(), maxTextures );
|
||||||
size_t materialBufferIndex = renderMode.metadata["materialBufferIndex"].as<size_t>();
|
|
||||||
size_t textureBufferIndex = renderMode.metadata["textureBufferIndex"].as<size_t>();
|
|
||||||
size_t drawCallBufferIndex = renderMode.metadata["drawCallBufferIndex"].as<size_t>();
|
|
||||||
graphic.updateBuffer( (void*) materials.data(), materials.size() * sizeof(pod::Material::Storage), materialBufferIndex, false );
|
|
||||||
graphic.updateBuffer( (void*) textures.data(), textures.size() * sizeof(pod::Texture::Storage), textureBufferIndex, false );
|
|
||||||
graphic.updateBuffer( (void*) drawCalls.data(), drawCalls.size() * sizeof(pod::DrawCall), drawCallBufferIndex, false );
|
|
||||||
}
|
}
|
||||||
// add lighting
|
// add lighting
|
||||||
int updateThreshold = metadata["system"]["config"]["engine"]["scenes"]["lights"]["update threshold"].as<size_t>();
|
for ( size_t i = 0; i < entities.size() && lights.size() < maxLights; ++i ) {
|
||||||
std::vector<UniformDescriptor::Light> lightPool;
|
|
||||||
lightPool.reserve( entities.size() );
|
|
||||||
|
|
||||||
for ( size_t i = 0; i < entities.size() && lightPool.size() < specializationConstants.maxLights; ++i ) {
|
|
||||||
auto& info = entities[i];
|
auto& info = entities[i];
|
||||||
uf::Entity* entity = info.entity;
|
uf::Entity* entity = info.entity;
|
||||||
|
|
||||||
@ -523,7 +493,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
|||||||
auto& camera = entity->getComponent<uf::Camera>();
|
auto& camera = entity->getComponent<uf::Camera>();
|
||||||
metadata["system"]["renderer"]["rendered"] = true;
|
metadata["system"]["renderer"]["rendered"] = true;
|
||||||
|
|
||||||
UniformDescriptor::Light light;
|
pod::Light::Storage light;
|
||||||
light.position = info.position;
|
light.position = info.position;
|
||||||
|
|
||||||
light.color = uf::vector::decode( metadata["light"]["color"], light.color );
|
light.color = uf::vector::decode( metadata["light"]["color"], light.color );
|
||||||
@ -536,6 +506,9 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
|||||||
if ( lightType == "point" ) light.type = 1;
|
if ( lightType == "point" ) light.type = 1;
|
||||||
else if ( lightType == "spot" ) light.type = 2;
|
else if ( lightType == "spot" ) light.type = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
light.mapIndex = -1;
|
||||||
|
|
||||||
light.depthBias = metadata["light"]["bias"]["shader"].as<float>();
|
light.depthBias = metadata["light"]["bias"]["shader"].as<float>();
|
||||||
|
|
||||||
if ( info.shadows && entity->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
|
if ( info.shadows && entity->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
|
||||||
@ -543,48 +516,48 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
|||||||
if ( metadata["system"]["renderer"]["mode"].as<std::string>() == "in-range" && --updateThreshold > 0 ) {
|
if ( metadata["system"]["renderer"]["mode"].as<std::string>() == "in-range" && --updateThreshold > 0 ) {
|
||||||
renderMode.execute = true;
|
renderMode.execute = true;
|
||||||
}
|
}
|
||||||
light.type = -abs(light.type);
|
size_t view = 0;
|
||||||
size_t shadows = 0;
|
|
||||||
for ( auto& attachment : renderMode.renderTarget.attachments ) {
|
for ( auto& attachment : renderMode.renderTarget.attachments ) {
|
||||||
if ( !(attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
if ( !(attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||||
if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue;
|
if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue;
|
||||||
|
|
||||||
auto& texture = graphic.material.textures.emplace_back();
|
graphic.material.textures.emplace_back().aliasAttachment(attachment);
|
||||||
texture.aliasAttachment(attachment);
|
|
||||||
++shadows;
|
light.mapIndex = textureSlot++;
|
||||||
}
|
light.view = camera.getView(view);
|
||||||
for ( size_t j = 0; j < shadows; ++j ) {
|
light.projection = camera.getProjection(view);
|
||||||
light.view = camera.getView(j);
|
lights.emplace_back(light);
|
||||||
light.projection = camera.getProjection(j);
|
|
||||||
lightPool.push_back(light);
|
++view;
|
||||||
}
|
}
|
||||||
|
light.mapIndex = -1;
|
||||||
} else {
|
} else {
|
||||||
lightPool.emplace_back(light);
|
lights.emplace_back(light);
|
||||||
graphic.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty);
|
|
||||||
}
|
}
|
||||||
}
|
uniforms->lengths.lights = std::min( lights.size(), maxLights );
|
||||||
{
|
|
||||||
size_t lightsAdded = 0;
|
|
||||||
for ( size_t i = 0; i < specializationConstants.maxLights && i < lightPool.size(); ++i, ++lightsAdded ) lights[i] = lightPool[i];
|
|
||||||
// std::cout << "Shadowmaps added: " << lightsAdded << "\t";
|
|
||||||
while ( lightsAdded++ < specializationConstants.maxLights ) {
|
|
||||||
graphic.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty);
|
|
||||||
}
|
|
||||||
// std::cout << "Total shadowmaps: " << lightsAdded << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
|
||||||
bool shouldUpdate = graphic.material.textures.size() != previousTextures.size();
|
bool shouldUpdate = graphic.material.textures.size() != previousTextures.size();
|
||||||
while ( !shouldUpdate && i < graphic.material.textures.size() ) {
|
for ( size_t i = 0; !shouldUpdate && i < previousTextures.size() && i < graphic.material.textures.size(); ++i ) {
|
||||||
auto& texture = graphic.material.textures[i];
|
if ( previousTextures[i] != graphic.material.textures[i].image )
|
||||||
auto& previousTexture = previousTextures[i];
|
shouldUpdate = true;
|
||||||
if ( texture.image != previousTexture ) shouldUpdate = true;
|
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
if ( shouldUpdate ) graphic.updatePipelines();
|
if ( shouldUpdate ) {
|
||||||
|
size_t lightBufferIndex = renderMode.metadata["lightBufferIndex"].as<size_t>();
|
||||||
|
size_t materialBufferIndex = renderMode.metadata["materialBufferIndex"].as<size_t>();
|
||||||
|
size_t textureBufferIndex = renderMode.metadata["textureBufferIndex"].as<size_t>();
|
||||||
|
size_t drawCallBufferIndex = renderMode.metadata["drawCallBufferIndex"].as<size_t>();
|
||||||
|
|
||||||
|
graphic.updateBuffer( (void*) lights.data(), uniforms->lengths.lights * sizeof(pod::Light::Storage), lightBufferIndex, false );
|
||||||
|
graphic.updateBuffer( (void*) materials.data(), uniforms->lengths.materials * sizeof(pod::Material::Storage), materialBufferIndex, false );
|
||||||
|
graphic.updateBuffer( (void*) textures.data(), uniforms->lengths.textures * sizeof(pod::Texture::Storage), textureBufferIndex, false );
|
||||||
|
graphic.updateBuffer( (void*) drawCalls.data(), uniforms->lengths.drawCalls * sizeof(pod::DrawCall), drawCallBufferIndex, false );
|
||||||
|
|
||||||
|
graphic.updatePipelines();
|
||||||
|
}
|
||||||
|
shader.updateUniform( "UBO", uniform );
|
||||||
}
|
}
|
||||||
shader.updateUniform( "UBO", uniform );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user