diff --git a/bin/data/shaders/display.subpass.frag.glsl b/bin/data/shaders/display.subpass.frag.glsl index d03af0ac..ca130791 100644 --- a/bin/data/shaders/display.subpass.frag.glsl +++ b/bin/data/shaders/display.subpass.frag.glsl @@ -1,11 +1,27 @@ #version 450 #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 = 1) const uint TEXTURES = 256; +layout (constant_id = 0) 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 { vec4 colorBase; vec4 colorEmissive; @@ -54,7 +70,9 @@ layout (input_attachment_index = 3, binding = 4) uniform subpassInput samplerDep layout (binding = 5) uniform sampler3D samplerNoise; 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 { Material materials[]; }; @@ -71,14 +89,6 @@ layout (location = 1) in flat uint inPushConstantPass; layout (location = 0) out vec4 outFragColor; -/* -const vec2 poissonDisk[4] = vec2[]( - vec2( -0.94201624, -0.39906216 ), - vec2( 0.94558609, -0.76890725 ), - vec2( -0.094184101, -0.92938870 ), - vec2( 0.34495938, 0.29387760 ) -); -*/ vec2 poissonDisk[16] = vec2[]( vec2( -0.94201624, -0.39906216 ), vec2( 0.94558609, -0.76890725 ), @@ -98,22 +108,6 @@ vec2 poissonDisk[16] = vec2[]( 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 { mat4 view[2]; mat4 projection[2]; @@ -150,11 +144,17 @@ struct Mode { layout (binding = 0) uniform UBO { Matrices matrices; - vec3 ambient; - float kexp; + Mode mode; Fog fog; - Light lights[LIGHTS]; + + uint lights; + uint materials; + uint textures; + uint drawCalls; + + vec3 ambient; + float kexp; } ubo; 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 ) { - vec3 point = position.world; - - vec4 positionClip = light.projection * light.view * vec4(point, 1.0); + vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0); positionClip.xyz /= positionClip.w; if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0; @@ -245,12 +243,12 @@ float shadowFactor( Light light, uint shadowMap ) { float factor = 1.0; // spot light - if ( light.type == -2 || light.type == -3 ) { + if ( light.type == 2 || light.type == 3 ) { float dist = length( positionClip.xy ); if ( dist > 0.5 ) return 0.0; // spot light with attenuation - if ( light.type == -3 ) { + if ( light.type == 3 ) { factor = 1.0 - (pow(dist * 2,2.0)); } } @@ -267,15 +265,16 @@ float shadowFactor( Light light, uint shadowMap ) { */ float eyeDepth = positionClip.z; - int samples = poissonDisk.length(); + + int samples = POISSON_DISK; 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 ) { // int index = i; // int index = int( float(samples) * random(gl_FragCoord.xyy, i) ) % samples; int index = int( float(samples) * random(floor(position.world.xyz * 1000.0), i)) % samples; - float lightDepth = texture(samplerShadows[shadowMap], uv + poissonDisk[index] / 700.0 ).r; + float lightDepth = texture(samplerTextures[shadowMap], uv + poissonDisk[index] / 700.0 ).r; if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples; } return factor; @@ -498,6 +497,7 @@ void fog( inout vec3 i, float scale ) { if ( ubo.fog.stepScale <= 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] ); 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)); @@ -536,6 +536,7 @@ void fog( inout vec3 i, float scale ) { } i.rgb = mix(ubo.fog.color.rgb, i.rgb, transmittance); } +#endif vec3 color = ubo.fog.color.rgb; float inner = ubo.fog.range.x; @@ -556,21 +557,14 @@ vec3 decodeNormals( vec2 enc ) { n.z = 1-f/2; 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 ) { - return 0 <= textureIndex && textureIndex < TEXTURES; + return 0 <= textureIndex && textureIndex < ubo.textures; } vec4 sampleTexture( uint drawId, int textureIndex, vec2 uv, vec4 base ) { if ( !validTextureIndex( textureIndex ) ) return base; 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 ) ); } @@ -595,7 +589,7 @@ void main() { uint drawId = ID.x; DrawCall drawCall = drawCalls[drawId]; - uint materialId = ID.y + 1; + uint materialId = ID.y; materialId += drawCall.materialIndex; Material material = materials[materialId]; @@ -609,26 +603,29 @@ void main() { #endif float M = material.factorMetallic; - float R = 0.5; //material.factorRoughness; + float R = material.factorRoughness * 4.0; float AO = material.factorOcclusion; bool usePbr = true; bool gammaCorrect = false; float litFactor = 1.0; vec3 fragColor = C.rgb * ubo.ambient.rgb * AO; - for ( uint i = 0; i < LIGHTS; ++i ) { - Light light = ubo.lights[i]; + for ( uint i = 0; i < ubo.lights; ++i ) { + Light light = lights[i]; if ( light.power <= 0.001 ) continue; + vec3 lightPositionWorld = light.position.xyz; light.position.xyz = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position.xyz, 1)); - if ( light.type < 0 ) { - float factor = shadowFactor( light, i ); - if ( factor <= 0.0001 ) continue; + + if ( 0 <= light.mapIndex && light.mapIndex < TEXTURES ) { + float factor = shadowFactor( light, light.mapIndex ); + // if ( factor <= 0.0001 ) continue; light.power *= factor; litFactor += light.power; } if ( light.power <= 0.0001 ) continue; + if ( usePbr ) { pbr( light, C.rgb, M, R, lightPositionWorld, fragColor ); } else diff --git a/bin/data/shaders/gltf.frag.glsl b/bin/data/shaders/gltf.frag.glsl index 1bd32b2d..e5419218 100644 --- a/bin/data/shaders/gltf.frag.glsl +++ b/bin/data/shaders/gltf.frag.glsl @@ -1,6 +1,7 @@ #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 (binding = 0) uniform sampler2D samplerTextures[TEXTURES]; @@ -72,18 +73,19 @@ vec4 sampleTexture( int textureIndex, vec2 uv, vec4 base ) { } void main() { -#if UF_DEFERRED_SAMPLING + vec4 C = vec4(0, 0, 0, 0); + vec3 P = inPosition; vec3 N = inNormal; +#if UF_DEFERRED_SAMPLING outUvs = fract(inUv); -#else + vec4 outAlbedo = vec4(0,0,0,0); +#endif +#if !UF_DEFERRED_SAMPLING || UF_CAN_DISCARD int materialId = int(inId.y); Material material = materials[materialId]; vec2 uv = fract(inUv.xy); - vec4 C = vec4(0, 0, 0, 0); - vec3 N = inNormal; - vec3 P = inPosition; float M = material.factorMetallic; float R = material.factorRoughness; float AO = material.factorOcclusion; @@ -96,8 +98,11 @@ void main() { { Texture t = textures[material.indexAlbedo + 1]; 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 if ( validTextureIndex( material.indexNormal ) ) { Texture t = textures[material.indexNormal + 1]; @@ -120,14 +125,10 @@ void main() { } #endif - if ( C.a < abs(material.factorAlphaCutoff) ) { - // outTransparency = C; - discard; - } else { - C.rgb *= inColor.rgb * C.a; - outAlbedo = vec4(C.rgb,1); - } + C.rgb *= inColor.rgb * C.a; + outAlbedo = vec4(C.rgb,1); #endif + outNormals = encodeNormals( N ); outId = ivec2(inId.w, inId.y); } diff --git a/engine/inc/uf/ext/gltf/graph.h b/engine/inc/uf/ext/gltf/graph.h index 6201800b..9f239e01 100644 --- a/engine/inc/uf/ext/gltf/graph.h +++ b/engine/inc/uf/ext/gltf/graph.h @@ -32,6 +32,18 @@ namespace pod { uf::renderer::Texture2D texture; }; 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 = ""; pod::Transform<> transform = {}; pod::Vector3f color = { 1, 1, 1 }; diff --git a/engine/src/ext/gltf/graph.cpp b/engine/src/ext/gltf/graph.cpp index 5a4c43ef..643674c9 100644 --- a/engine/src/ext/gltf/graph.cpp +++ b/engine/src/ext/gltf/graph.cpp @@ -47,15 +47,15 @@ namespace { if ( graph.mode & ext::gltf::LoadMode::LOAD ) { if ( graph.mode & ext::gltf::LoadMode::SEPARATE ) { 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 { - 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 { 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 { - 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); diff --git a/engine/src/ext/vulkan/buffer.cpp b/engine/src/ext/vulkan/buffer.cpp index 6f4f7048..c3f53f6e 100644 --- a/engine/src/ext/vulkan/buffer.cpp +++ b/engine/src/ext/vulkan/buffer.cpp @@ -216,8 +216,8 @@ void ext::vulkan::Buffers::updateBuffer( void* data, VkDeviceSize length, Buffer 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"); } else { - length = buffer.allocationInfo.size; VK_VALIDATION_MESSAGE("Mismatch buffer update: Requesting " << buffer.allocationInfo.size << ", got " << length << ", resetting for safety"); + length = buffer.allocationInfo.size; } // assert(buffer.allocationInfo.size > length); } diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index a5618f52..77dac299 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -8,6 +8,9 @@ #include #include +#define VK_DEBUG_VALIDATION_MESSAGE(x)\ + //VK_VALIDATION_MESSAGE(x); + namespace { 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); if ( size <= 0 ) break; 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_t misalignment = size % device.properties.limits.minStorageBufferOffsetAlignment; 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; } { - //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(); uniform.create( size ); } @@ -519,16 +522,16 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st if ( size <= 0 ) continue; // not a multiple of 4, for some reason 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; size *= 4; } 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; } - //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(); pushConstant.create( size ); @@ -557,7 +560,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st } if ( specializationSize > 0 ) { 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; 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) ); } break; 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; } member["name"] = name; member["size"] = size; member["default"] = member["value"]; - //VK_VALIDATION_MESSAGE("Specialization constant: " << member["type"].as() << " " << name << " = " << member["value"].dump() << "; at offset " << offset << " for shader " << filename ); + VK_DEBUG_VALIDATION_MESSAGE("Specialization constant: " << member["type"].as() << " " << name << " = " << member["value"].dump() << "; at offset " << offset << " for shader " << filename ); metadata["specializationConstants"].emplace_back(member); memcpy( &s[offset], &buffer, size ); @@ -675,7 +678,7 @@ bool ext::vulkan::Shader::validate() { if ( it == uniforms.end() ) break; auto& uniform = *(it++); 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.create(buffer.allocationInfo.size); valid = false; @@ -795,7 +798,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des for ( auto& pushConstant : shader.pushConstants ) { size_t len = pushConstant.data().len; 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; 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]; // failsafe, because for some reason things break if ( payload["validate"].as() && 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() ? payload["value"].as() : payload["default"].as(); } payload["value"] = v; @@ -1001,7 +1004,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des uint32_t& v = ((uint32_t*) s)[i]; // failsafe, because for some reason things break if ( payload["validate"].as() && 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() ? payload["value"].as() : payload["default"].as(); } payload["value"] = v; @@ -1009,13 +1012,13 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des float& v = ((float*) s)[i]; // failsafe, because for some reason things break if ( payload["validate"].as() && 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() ? payload["value"].as() : payload["default"].as(); } 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; 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; return; PIPELINE_INITIALIZATION_INVALID: 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 { this->initialize( graphic, descriptor ); 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 ) { if ( descriptor.pBufferInfo ) { 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; } } if ( descriptor.pImageInfo ) { + if ( descriptor.pImageInfo[i].imageView == 0x0 ) { + VK_DEBUG_VALIDATION_MESSAGE("Null image view, replacing with fallback texture..."); + auto pointer = const_cast(&descriptor.pImageInfo[i]); + *pointer = emptyTexture.descriptor; + } 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(&descriptor.pImageInfo[i]); pointer->imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; } 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(&descriptor.pImageInfo[i]); pointer->sampler = emptyTexture.sampler.sampler; } @@ -1287,7 +1295,7 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip PIPELINE_UPDATE_INVALID: 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 { this->update( graphic, descriptor ); 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 ) { if ( !process ) return; if ( !this->hasPipeline( descriptor ) ) { - //VK_VALIDATION_MESSAGE(this << ": has no valid pipeline"); + VK_DEBUG_VALIDATION_MESSAGE(this << ": has no valid pipeline"); return; } auto& pipeline = this->getPipeline( descriptor ); 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; } diff --git a/engine/src/ext/vulkan/rendermodes/deferred.cpp b/engine/src/ext/vulkan/rendermodes/deferred.cpp index 4e1d7eb9..ae9cbc40 100644 --- a/engine/src/ext/vulkan/rendermodes/deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/deferred.cpp @@ -283,24 +283,31 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { auto& shader = blitter.material.shaders.back(); struct SpecializationConstant { - uint32_t maxLights = 256; - uint32_t maxTextures = 256; + uint32_t maxTextures = 512; }; auto& specializationConstants = shader.specializationConstants.get(); auto& metadata = scene.getComponent(); - specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(); + size_t maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(); specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as(); for ( auto& binding : shader.descriptorSetLayoutBindings ) { if ( binding.descriptorCount > 1 ) - binding.descriptorCount = specializationConstants.maxLights; + binding.descriptorCount = specializationConstants.maxTextures; } + std::vector lights(maxLights); std::vector materials(specializationConstants.maxTextures); std::vector textures(specializationConstants.maxTextures); std::vector drawCalls(specializationConstants.maxTextures); 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( (void*) materials.data(), materials.size() * sizeof(pod::Material::Storage), diff --git a/ext/behaviors/light/behavior.cpp b/ext/behaviors/light/behavior.cpp index 5a45034e..f4000719 100644 --- a/ext/behaviors/light/behavior.cpp +++ b/ext/behaviors/light/behavior.cpp @@ -169,41 +169,22 @@ void ext::LightBehavior::tick( uf::Object& self ) { // omni light if ( metadata["light"]["shadows"].as() && metadata["light"]["type"].as() == "point" ) { 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> rotations = { + /* {0, 0, 0, 1}, {0, 0.707107, 0, -0.707107}, {0, 1, 0, 0}, {0, 0.707107, 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 }, 1 * 1.57079633 ), uf::quaternion::axisAngle( { 0, 1, 0 }, 2 * 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 }, 3 * 1.57079633 ), - */ }; for ( size_t i = 0; i < rotations.size(); ++i ) { auto transform = camera.getTransform(); diff --git a/ext/behaviors/scene/behavior.cpp b/ext/behaviors/scene/behavior.cpp index 0b789899..3bd37fb7 100644 --- a/ext/behaviors/scene/behavior.cpp +++ b/ext/behaviors/scene/behavior.cpp @@ -168,6 +168,7 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) { float n = perlins[i]; n = n - floor(n); float normalized = (n - low) / (high - low); + if ( normalized >= 1.0f ) normalized = 1.0f; pixels[i] = static_cast(floor(normalized * 255)); } 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(); auto& controllerTransform = controller.getComponent>(); std::vector blitters = renderMode.getBlitters(); + + size_t maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as(); struct UniformDescriptor { struct Matrices { alignas(16) pod::Matrix4f view[2]; alignas(16) pod::Matrix4f projection[2]; } matrices; - alignas(16) pod::Vector4f ambient; struct Mode { alignas(8) pod::Vector2ui type; alignas(8) pod::Vector2ui padding; @@ -311,25 +313,18 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { alignas(4) float padding2; alignas(4) float padding3; } fog; - struct Light { - alignas(16) pod::Vector4f position; - alignas(16) pod::Vector4f color; - - alignas(4) int32_t type = 0; - alignas(4) float depthBias = 0; - alignas(4) float padding1 = 0; - alignas(4) float padding2 = 0; - - alignas(16) pod::Matrix4f view; - alignas(16) pod::Matrix4f projection; - } lights; + struct { + alignas(4) uint32_t lights = 0; + alignas(4) uint32_t materials = 0; + alignas(4) uint32_t textures = 0; + alignas(4) uint32_t drawCalls = 0; + } lengths; + alignas(16) pod::Vector4f ambient; }; struct SpecializationConstant { - uint32_t maxLights = 256; - uint32_t maxTextures = 256; + uint32_t maxTextures = 512; } specializationConstants; - specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(); - specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as(); + specializationConstants.maxTextures = maxTextures; struct LightInfo { uf::Entity* entity = NULL; @@ -406,7 +401,6 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { uint8_t* buffer = (uint8_t*) (void*) uniform; UniformDescriptor* uniforms = (UniformDescriptor*) buffer; - UniformDescriptor::Light* lights = (UniformDescriptor::Light*) &buffer[sizeof(UniformDescriptor) - sizeof(UniformDescriptor::Light)]; for ( std::size_t i = 0; i < 2; ++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; } - 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 previousTextures; for ( auto& texture : graphic.material.textures ) previousTextures.emplace_back(texture.image); + graphic.material.textures.clear(); // add noise texture graphic.material.textures.emplace_back().aliasTexture(this->getComponent()); + + size_t updateThreshold = metadata["system"]["config"]["engine"]["scenes"]["lights"]["update threshold"].as(); + size_t maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(); + size_t textureSlot = 0; + + std::vector lights; + lights.reserve( maxLights ); + + std::vector materials; + materials.reserve(maxTextures); + materials.emplace_back().colorBase = {0,0,0,0}; + + std::vector textures; + textures.reserve(maxTextures); + + std::vector drawCalls; + drawCalls.reserve(maxTextures); + // add materials { - size_t attachedTextures = 0; - std::vector materials; - materials.reserve(specializationConstants.maxTextures); - - std::vector textures; - textures.reserve(specializationConstants.maxTextures); - - std::vector drawCalls; - drawCalls.reserve(specializationConstants.maxTextures); - - materials.emplace_back().colorBase = {0,0,0,0}; - for ( auto* entity : graphs ) { auto& graph = *entity; + + drawCalls.emplace_back(pod::DrawCall{ + materials.size(), + graph.materials.size(), + textures.size(), + graph.textures.size() + }); - size_t startMaterial = materials.size() - 1; - size_t startTexture = textures.size(); + for ( auto& material : graph.materials ) materials.emplace_back( material.storage ); + 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 ) { if ( !texture.texture.device ) continue; - ++attachedTextures; + graphic.material.textures.emplace_back().aliasTexture(texture.texture); + ++textureSlot; + if ( graph.atlas ) break; } } - while ( attachedTextures++ < specializationConstants.maxTextures ) { - graphic.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty); - } - - size_t materialBufferIndex = renderMode.metadata["materialBufferIndex"].as(); - size_t textureBufferIndex = renderMode.metadata["textureBufferIndex"].as(); - size_t drawCallBufferIndex = renderMode.metadata["drawCallBufferIndex"].as(); - 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 ); + + uniforms->lengths.materials = std::min( materials.size(), maxTextures ); + uniforms->lengths.textures = std::min( textures.size(), maxTextures ); + uniforms->lengths.drawCalls = std::min( drawCalls.size(), maxTextures ); } // add lighting - int updateThreshold = metadata["system"]["config"]["engine"]["scenes"]["lights"]["update threshold"].as(); - std::vector lightPool; - lightPool.reserve( entities.size() ); - - for ( size_t i = 0; i < entities.size() && lightPool.size() < specializationConstants.maxLights; ++i ) { + for ( size_t i = 0; i < entities.size() && lights.size() < maxLights; ++i ) { auto& info = entities[i]; uf::Entity* entity = info.entity; @@ -523,7 +493,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { auto& camera = entity->getComponent(); metadata["system"]["renderer"]["rendered"] = true; - UniformDescriptor::Light light; + pod::Light::Storage light; light.position = info.position; 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; else if ( lightType == "spot" ) light.type = 2; } + + light.mapIndex = -1; + light.depthBias = metadata["light"]["bias"]["shader"].as(); if ( info.shadows && entity->hasComponent() ) { @@ -543,48 +516,48 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { if ( metadata["system"]["renderer"]["mode"].as() == "in-range" && --updateThreshold > 0 ) { renderMode.execute = true; } - light.type = -abs(light.type); - size_t shadows = 0; + size_t view = 0; for ( auto& attachment : renderMode.renderTarget.attachments ) { if ( !(attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue; - auto& texture = graphic.material.textures.emplace_back(); - texture.aliasAttachment(attachment); - ++shadows; - } - for ( size_t j = 0; j < shadows; ++j ) { - light.view = camera.getView(j); - light.projection = camera.getProjection(j); - lightPool.push_back(light); + graphic.material.textures.emplace_back().aliasAttachment(attachment); + + light.mapIndex = textureSlot++; + light.view = camera.getView(view); + light.projection = camera.getProjection(view); + lights.emplace_back(light); + + ++view; } + light.mapIndex = -1; } else { - lightPool.emplace_back(light); - graphic.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty); + lights.emplace_back(light); } - } - { - 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; + uniforms->lengths.lights = std::min( lights.size(), maxLights ); } { - size_t i = 0; bool shouldUpdate = graphic.material.textures.size() != previousTextures.size(); - while ( !shouldUpdate && i < graphic.material.textures.size() ) { - auto& texture = graphic.material.textures[i]; - auto& previousTexture = previousTextures[i]; - if ( texture.image != previousTexture ) shouldUpdate = true; - ++i; + for ( size_t i = 0; !shouldUpdate && i < previousTextures.size() && i < graphic.material.textures.size(); ++i ) { + if ( previousTextures[i] != graphic.material.textures[i].image ) + shouldUpdate = true; } - if ( shouldUpdate ) graphic.updatePipelines(); + if ( shouldUpdate ) { + size_t lightBufferIndex = renderMode.metadata["lightBufferIndex"].as(); + size_t materialBufferIndex = renderMode.metadata["materialBufferIndex"].as(); + size_t textureBufferIndex = renderMode.metadata["textureBufferIndex"].as(); + size_t drawCallBufferIndex = renderMode.metadata["drawCallBufferIndex"].as(); + + 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 ); } } }