Commit for 2021.02.05.7z

This commit is contained in:
mrq 2021-02-05 00:00:00 -06:00
parent 77f24467e9
commit 910039a877
9 changed files with 209 additions and 230 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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