managed to fix the disgusting icky input lag at specific frametimes (because the swapchain was rendering to the wrong frame for presentation), attempting to fix a regression with shadowmaps being icky

This commit is contained in:
ecker 2026-06-12 22:28:35 -05:00
parent 8aee000b05
commit 7034da71de
24 changed files with 266 additions and 301 deletions

View File

@ -2,7 +2,6 @@
"engine": {
"scenes": {
"start": "StartMenu",
"matrix": { "reverseInfinite": true },
"lights": { "enabled": true,
"lightmaps": false,
"max": 32,
@ -10,7 +9,7 @@
"enabled": true,
"update": 4,
"max": 16,
"samples": 2
"samples": 1
},
"bloom": {
"scale": 1.0,
@ -109,19 +108,19 @@
"invariant": {
"default stage buffers": true,
"default defer buffer destroy": true,
"default command buffer immediate": false,
"n-buffered uniform": false,
"multithreaded recording": true
"default command buffer immediate": true,
"n-buffered uniform": true,
"multithreaded recording": false
},
"pipelines": {
"deferred": true,
"gui": true,
"vsync": true, // vsync on vulkan side rather than engine-side
"vsync": false, // vsync on vulkan side rather than engine-side
"hdr": true,
"vxgi": true, // to-do: fix issues
"vxgi": false, // to-do: fix issues
"culling": false,
"bloom": true,
"dof": true,
"bloom": false,
"dof": false,
"rt": false,
"fsr": false,
"postProcess": false // "postProcess.chromab" // false

View File

@ -24,8 +24,8 @@
"power": 100,
"fov": 90,
"bias": {
"constant": 1.25,
"slope": 1.75,
"constant": -1.25,
"slope": -1.75,
"shader": 0.00001 // 0.000005 //0.000000005
},
"radius": [0.5, 0],

View File

@ -113,7 +113,7 @@
"settings": {
"fixed": false,
"fov" : 90.0,
"clip" : [ 0.1, 64.0 ],
"clip" : [ 0.1, 0 ],
"size" : [ 0, 0 ]
}
},

View File

@ -56,13 +56,10 @@ float omniShadowMap( const Light light, float def ) {
if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0;
if ( positionClip.y < -1 || positionClip.y >= 1 ) return 0.0;
if ( positionClip.z < -1 || positionClip.z >= 1 ) return 0.0;
const float eyeDepthScale = 1.0;
const float sampledDepthScale = light.view[1][1]; // light view matricies will incorporate scaling factors for some retarded reason, so we need to rescale it by grabbing from here, hopefully it remains coherent between all light matrices to ever exist in engine
if ( positionClip.z <= 0 || positionClip.z >= 1 ) return 0.0;
const float bias = light.depthBias;
const float eyeDepth = abs(positionClip.z / positionClip.w) * eyeDepthScale;
const float eyeDepth = abs(positionClip.z / positionClip.w);
const vec3 sampleOffsetDirections[20] = {
vec3( 1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1),
@ -77,13 +74,13 @@ float omniShadowMap( const Light light, float def ) {
// cubemap point light
if ( light.typeMap == 1 ) {
if ( samples < 1 ) {
sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D).r * sampledDepthScale;
sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D).r ;
} else {
for ( int i = 0; i < samples; ++i ) {
const int idx = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
vec2 poisson = poissonDisk[idx] / 700.0;
vec3 P = vec3( poisson.xy, (poisson.x + poisson.y) * 0.5 );
sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D + P ).r * sampledDepthScale;
sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D + P ).r ;
if ( eyeDepth < sampled - bias ) factor -= 1.0 / samples;
}
return factor;
@ -92,11 +89,11 @@ float omniShadowMap( const Light light, float def ) {
} else if ( light.typeMap == 2 ) {
const vec2 uv = positionClip.xy * 0.5 + 0.5;
if ( samples < 1 ) {
sampled = texture(samplerTextures[nonuniformEXT(light.indexMap + index)], uv).r * sampledDepthScale;
sampled = texture(samplerTextures[nonuniformEXT(light.indexMap + index)], uv).r ;
} else {
for ( int i = 0; i < samples; ++i ) {
const int idx = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
sampled = texture(samplerTextures[nonuniformEXT(light.indexMap + index)], uv + poissonDisk[idx] / 700.0 ).r * sampledDepthScale;
sampled = texture(samplerTextures[nonuniformEXT(light.indexMap + index)], uv + poissonDisk[idx] / 700.0 ).r ;
if ( eyeDepth < sampled - bias ) factor -= 1.0 / samples;
}
return factor;

View File

@ -188,6 +188,7 @@ struct Surface {
vec4 light;
vec4 fragment;
vec2 fragCoord;
} surface;
// MSAA info

View File

@ -63,7 +63,7 @@ layout( push_constant ) uniform PushBlock {
#include "../../../common/structs.h"
layout (binding = 11, set = 0) uniform Camera {
Viewport viewport[2];
Viewport viewport[6];
} camera;
layout (binding = 12, set = 0) uniform UBO {
@ -165,7 +165,6 @@ void postProcess() {
if ( ubo.settings.mode.type > 0x0000 ) {
uvec2 renderSize = imageSize(imageColor).xy;
vec2 inUv = (vec2(gl_GlobalInvocationID.xy) / vec2(renderSize)) * 2.0f - 1.0f;
if ( true ) {
// if ( ubo.settings.mode.type == 0x0001 ) outFragColor = vec4(surface.barycentric.rgb, 1);
if ( ubo.settings.mode.type == 0x0001 ) outFragColor = vec4(surface.material.albedo.rgb, 1);
@ -189,6 +188,7 @@ void populateSurface() {
const uvec2 renderSize = imageSize(imageColor).xy;
if ( gl_GlobalInvocationID.x >= renderSize.x || gl_GlobalInvocationID.y >= renderSize.y /*|| gl_GlobalInvocationID.z > PushConstant.pass*/ ) return;
surface.fragCoord = (vec2(gl_GlobalInvocationID.xy) / vec2(renderSize)) * 2.0f - 1.0f;
surface.pass = gl_GlobalInvocationID.z;
surface.fragment = vec4(0);
surface.light = vec4(0);
@ -200,7 +200,6 @@ void populateSurface() {
float depth = 0.0;
{
vec2 inUv = (vec2(gl_GlobalInvocationID.xy) / vec2(renderSize)) * 2.0f - 1.0f;
#if USE_CAMERA_VIEWPORT
const mat4 iProjection = inverse( camera.viewport[surface.pass].projection );
@ -211,8 +210,8 @@ void populateSurface() {
const mat4 iProjection = ubo.eyes[surface.pass].iProjection;
const mat4 iProjectionView = /*iProjection * iView;*/ inverse( ubo.eyes[surface.pass].projection * mat4(mat3(ubo.eyes[surface.pass].view)) );
#endif
const vec4 near4 = iProjectionView * (vec4(inUv, -1.0, 1.0));
const vec4 far4 = iProjectionView * (vec4(inUv, 1.0, 1.0));
const vec4 near4 = iProjectionView * (vec4(surface.fragCoord, -1.0, 1.0));
const vec4 far4 = iProjectionView * (vec4(surface.fragCoord, 1.0, 1.0));
const vec3 near3 = near4.xyz / near4.w;
const vec3 far3 = far4.xyz / far4.w;
@ -221,7 +220,7 @@ void populateSurface() {
depth = IMAGE_LOAD(samplerDepth).r;
vec4 eye = iProjection * vec4(inUv, depth, 1.0);
vec4 eye = iProjection * vec4(surface.fragCoord, depth, 1.0);
eye /= eye.w;
surface.position.eye = eye.xyz;

View File

@ -22,7 +22,7 @@ layout( push_constant ) uniform PushBlock {
} PushConstant;
layout (binding = 0) uniform Camera {
Viewport viewport[PASSES];
Viewport viewport[6];
} camera;
layout (std140, binding = 1) readonly buffer DrawCommands {

View File

@ -17,6 +17,7 @@ namespace ext {
0
};
VkDeviceSize alignment = 0;
VkDeviceSize stride = 0;
void* mapped = nullptr;
mutable size_t address = {};
mutable bool written = false; // could technically be deduced with the address being set

View File

@ -8,6 +8,9 @@
#define UF_GRAPHIC_POINTERED_USERDATA 1
#define IS_DYNAMIC(name) true
// name.ends_with("_d")
namespace ext {
namespace vulkan {
#if UF_GRAPHIC_POINTERED_USERDATA

View File

@ -21,8 +21,8 @@ namespace pod {
pod::Matrix4f view;
pod::Matrix4f projection;
} matrices[uf::camera::maxViews];
size_t views = 1;
} viewport;
size_t views = 1;
bool stereoscopic = false;
};
}

View File

@ -486,86 +486,27 @@ pod::Matrix4t<T> /*UF_API*/ uf::matrix::orthographic( T l, T r, T b, T t ) {
}
template<typename T>
pod::Matrix4t<T> /*UF_API*/ uf::matrix::perspective( T fov, T raidou, T znear, T zfar ) {
if (uf::matrix::reverseInfiniteProjection) {
T f = static_cast<T>(1) / tan(static_cast<T>(0.5) * fov);
#if UF_USE_OPENGL
pod::Matrix4t<T> m = uf::matrix::identity<T>();
m(0,0) = f / raidou;
m(1,1) = f;
m(2,2) = 0;
m(2,3) = znear;
m(3,2) = 1;
m(3,3) = 0;
return m;
#elif UF_USE_VULKAN
pod::Matrix4t<T> m = uf::matrix::identity<T>();
m(0,0) = f / raidou;
m(1,1) = -f; // Vulkan flips Y
m(2,2) = 0;
m(2,3) = znear;
m(3,2) = 1;
m(3,3) = 0;
return m;
#endif
} else {
T range = znear - zfar;
T f = tan(static_cast<T>(0.5) * fov);
pod::Matrix4t<T> m = uf::matrix::identity<T>();
T Sx = static_cast<T>(1) / (f * raidou);
T Sy = static_cast<T>(1) / f;
T Sz = (zfar + znear) / range;
T Pz = (static_cast<T>(2) * zfar * znear) / range;
#if UF_USE_VULKAN
Sy = -Sy; // Vulkan NDC has inverted Y
#endif
pod::Matrix4t<T> m = uf::matrix::identity<T>();
m(0,0) = Sx;
m(1,1) = Sy;
m(2,2) = Sz;
m(2,3) = Pz;
m(3,2) = -1;
m(3,3) = 0;
return m;
}
#if 0
if ( uf::matrix::reverseInfiniteProjection ) {
T f = static_cast<T>(1) / tan( static_cast<T>(0.5) * fov );
#if UF_USE_OPENGL
return pod::Matrix4t<T>({
f / raidou, 0, 0, 0,
0, f, 0, 0,
0, 0, 0, 1,
0, 0, znear, 0
});
#elif UF_USE_VULKAN
return pod::Matrix4t<T>({
f / raidou, 0, 0, 0,
0, -f, 0, 0,
0, 0, 0, 1,
0, 0, znear, 0
});
#endif
} else {
T range = znear - zfar;
T f = tan( static_cast<T>(0.5) * fov );
T Sx = static_cast<T>(1) / (f * raidou);
T Sy = static_cast<T>(1) / f;
T Sz = (-znear - zfar) / range;
T Pz = static_cast<T>(2) * zfar * znear / range;
#if UF_USE_VULKAN
Sy = -Sy;
#endif
return pod::Matrix4t<T>({
Sx, 0, 0, 0,
0, Sy, 0, 0,
0, 0, Sz, 1,
0, 0, Pz, 0
});
}
T f = static_cast<T>(1) / tan(static_cast<T>(0.5) * fov);
m(0,0) = f / raidou;
m(1,1) = f;
#if UF_USE_VULKAN
m(1,1) = -f;
#endif
m(3,2) = 1;
m(3,3) = 0;
if ( zfar <= 0 ) {
m(2,2) = 0;
m(2,3) = znear;
} else {
T range = zfar - znear;
m(2,2) = zfar / range;
m(2,3) = -(zfar * znear) / range;
}
return m;
}
template<typename T> T& uf::matrix::copy( T& destination, const T& source ) {
FOR_EACH(T::rows * T::columns, {

View File

@ -453,6 +453,8 @@ namespace ext {
bool test = true;
bool write = true;
uf::renderer::enums::Compare::type_t operation = uf::renderer::enums::Compare::GREATER_OR_EQUAL;
float min = 1.0f;
float max = 0.0f;
struct {
bool enable = false;
float constant = 0;

View File

@ -93,7 +93,6 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
} else {
size = pod::Vector2ui{ uf::renderer::settings::width, uf::renderer::settings::height };
}
if ( radius.y < radius.x ) radius.y = 2048;
camera.setProjection( uf::matrix::perspective( fov, (float) size.x / (float) size.y, radius.x, radius.y ) );
camera.update();
@ -218,7 +217,7 @@ void ext::LightBehavior::tick( uf::Object& self ) {
if ( /*renderMode.execute*/ renderMode.metadata.limiter.execute && !metadata.renderer.external ) {
auto& camera = this->getComponent<uf::Camera>();
auto& pod = camera.data();
pod.viewport.views = 6;
pod.views = 6;
// omni light
if ( metadata.shadows && std::abs(metadata.type) == 1 ) {
auto transform = camera.getTransform();

View File

@ -13,6 +13,7 @@ namespace ext {
EXT_BEHAVIOR_DEFINE_FUNCTIONS();
UF_BEHAVIOR_DEFINE_METADATA(
pod::Vector3f color = {1,1,1};
pod::Vector2f radius = { 0.001f, 32.0f };
float power = 0.0f;
float bias = 0.0f;
bool shadows = false;

View File

@ -560,7 +560,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
LightInfo& info = entities.emplace_back(LightInfo{
.entity = entity,
.position = flatten.position,
.range = 0,
.range = MAX(metadata.radius.x, metadata.radius.y),
.color = metadata.color,
.intensity = metadata.power,
.distance = uf::vector::magnitude( uf::vector::subtract( flatten.position, controllerTransform.position ) ),
@ -1265,9 +1265,11 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
// trigger an update when we have differing bound texture sizes
bool shouldUpdate = metadata.shader.invalidated || graphic.material.textures.size() != previousTextures.size();
/*
for ( uint32_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();

View File

@ -208,7 +208,7 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
for ( auto& t : sceneTextures.voxels.output ) shader.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.outputMipmaps ) shader.textures.emplace_back().aliasTexture(t);
metadata.atomicCounter.initialize( (const void*) nullptr, sizeof(::AtomicCounter) * 1, uf::renderer::enums::Buffer::STORAGE );
metadata.atomicCounter.initialize( (const void*) nullptr, sizeof(::AtomicCounter) * 1, uf::renderer::enums::Buffer::STORAGE | VK_BUFFER_USAGE_TRANSFER_DST_BIT );
shader.aliasBuffer("atomicCounter", metadata.atomicCounter);
}
#endif

View File

@ -723,11 +723,7 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M
if ( mode == "cw" ) graphic.descriptor.frontFace = uf::renderer::enums::Face::CW;
else if ( mode == "ccw" ) graphic.descriptor.frontFace = uf::renderer::enums::Face::CCW;
else if ( mode == "auto" ) {
if ( uf::matrix::reverseInfiniteProjection ) {
graphic.descriptor.frontFace = graphMetadataJson["renderer"]["invert"].as<bool>(true) ? uf::renderer::enums::Face::CW : uf::renderer::enums::Face::CCW;
} else {
graphic.descriptor.frontFace = graphMetadataJson["renderer"]["invert"].as<bool>(true) ? uf::renderer::enums::Face::CW : uf::renderer::enums::Face::CCW;
}
graphic.descriptor.frontFace = graphMetadataJson["renderer"]["invert"].as<bool>(true) ? uf::renderer::enums::Face::CW : uf::renderer::enums::Face::CCW;
}
else UF_MSG_WARNING("Invalid Face enum string specified: {}", mode);
}
@ -1358,12 +1354,21 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
#else
metadata.system.ignoreGraph = graphMetadataJson["debug"]["static"].as<bool>();
#endif
float powerScale = graphMetadataJson["lights"]["scale"].as<float>(1);
const float LIGHT_POWER_CUTOFF = 0.005f;
float power = l.intensity * graphMetadataJson["lights"]["scale"].as<float>(1);
float range = l.range;
if ( range <= 0.0f ) {
if ( power > LIGHT_POWER_CUTOFF ) {
range = std::sqrt( (power / LIGHT_POWER_CUTOFF) - 1.0f );
} else {
range = 0.001f;
}
}
uf::Serializer metadataLight;
metadataLight["radius"][0] = 0.001;
metadataLight["radius"][1] = l.range;
metadataLight["power"] = l.intensity * powerScale;
metadataLight["radius"][0] = range;
metadataLight["radius"][1] = 0.001;
metadataLight["power"] = power;
metadataLight["color"][0] = l.color.x;
metadataLight["color"][1] = l.color.y;
@ -1375,10 +1380,11 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
if ( uf::string::matched( node.name, R"(/\bspot\b/)" ) ) {
metadataLight["type"] = "spot";
}
/*
if ( ext::json::isArray( graphMetadataJson["lights"]["radius"] ) ) {
metadataLight["radius"] = graphMetadataJson["lights"]["radius"];
}
*/
if ( graphMetadataJson["lights"]["bias"].is<float>() ) {
metadataLight["bias"] = graphMetadataJson["lights"]["bias"].as<float>();
}

View File

@ -15,6 +15,7 @@ void ext::vulkan::Buffer::swap( ext::vulkan::Buffer& buffer ) {
std::swap(this->memory, buffer.memory);
std::swap(this->descriptor, buffer.descriptor);
std::swap(this->alignment, buffer.alignment);
std::swap(this->stride, buffer.stride);
std::swap(this->address, buffer.address);
std::swap(this->mapped, buffer.mapped);
std::swap(this->usage, buffer.usage);
@ -37,6 +38,7 @@ void ext::vulkan::Buffer::aliasBuffer( const ext::vulkan::Buffer& buffer ) {
this->memory = buffer.memory;
this->descriptor = buffer.descriptor;
this->alignment = buffer.alignment;
this->stride = buffer.alignment;
this->address = buffer.address;
this->mapped = buffer.mapped;
this->usage = buffer.usage;
@ -91,7 +93,7 @@ size_t ext::vulkan::Buffer::getLength( ) const {
return allocationInfo.size;
}
size_t ext::vulkan::Buffer::getOffset( size_t i ) const {
return this->getLength() / this->count * i;
return this->stride * i;
}
ext::vulkan::Buffer::~Buffer() {
@ -117,6 +119,7 @@ void ext::vulkan::Buffer::destroy(bool defer) {
this->memory = {};
this->descriptor = {};
// this->alignment = {};
this->stride = {};
this->address = {};
this->mapped = {};
// this->usage = {};
@ -132,11 +135,12 @@ void ext::vulkan::Buffer::initialize( const void* data, VkDeviceSize length, VkB
if ( this->staged ) usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; // implicitly set properties
// assume all UBOs are dynamic
auto totalLength = length;
auto totalLength = (this->stride = length);
if ( VK_UBO_USE_N_BUFFERS && usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ) {
this->count = ext::vulkan::swapchain.buffers;
this->alignment = device->properties.limits.minUniformBufferOffsetAlignment;
totalLength = ALIGNED_SIZE( length, this->alignment ) * this->count;
this->stride = ALIGNED_SIZE( length, this->alignment );
totalLength = this->stride * this->count;
}
VK_CHECK_RESULT(device->createBuffer( nullptr, totalLength, usage, memoryProperties, *this ));

View File

@ -323,15 +323,8 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
descriptor.depth.write,
descriptor.depth.operation
);
if ( uf::matrix::reverseInfiniteProjection ) {
depthStencilState.depthCompareOp = ext::vulkan::enums::Compare::GREATER_OR_EQUAL;
depthStencilState.minDepthBounds = 1.0f;
depthStencilState.maxDepthBounds = 0.0f;
} else {
depthStencilState.depthCompareOp = ext::vulkan::enums::Compare::LESS;
depthStencilState.minDepthBounds = 0.0f;
depthStencilState.maxDepthBounds = 1.0f;
}
depthStencilState.minDepthBounds = descriptor.depth.min;
depthStencilState.maxDepthBounds = descriptor.depth.max;
VkPipelineViewportStateCreateInfo viewportState = ext::vulkan::initializers::pipelineViewportStateCreateInfo(
1, 1, 0
);
@ -532,6 +525,7 @@ void ext::vulkan::DescriptorSets::record( const Graphic& graphic, const GraphicD
// create dynamic offset ranges
STATIC_THREAD_LOCAL(uf::stl::vector<uint32_t>, dynamicOffsets);
static thread_local std::map<uint32_t, uint32_t> bindingStrides; bindingStrides.clear();
RenderMode& renderMode = ext::vulkan::getRenderMode(descriptor.renderMode, true);
@ -556,14 +550,19 @@ void ext::vulkan::DescriptorSets::record( const Graphic& graphic, const GraphicD
if ( descriptor.bind.point == VK_PIPELINE_BIND_POINT_GRAPHICS ) bound = true;
else continue;
}
if ( VK_UBO_USE_N_BUFFERS )
dynamicOffsets.insert( dynamicOffsets.end(), shader->metadata.dynamicRanges.begin(), shader->metadata.dynamicRanges.end() );
if ( VK_UBO_USE_N_BUFFERS ) {
for ( const auto& [name, uniform] : shader->metadata.definitions.uniforms ) {
if ( IS_DYNAMIC(name) ) {
bindingStrides[uniform.binding] = uniform.size;
}
}
}
}
for ( auto& dynamicOffset : dynamicOffsets ) {
dynamicOffset *= offset;
}
for ( const auto& [binding, stride] : bindingStrides ) {
dynamicOffsets.emplace_back( stride * offset );
}
// no matching bind point for shaders, skip
if ( !bound ) {
@ -2152,7 +2151,7 @@ void ext::vulkan::GraphicDescriptor::parse( ext::json::Value& metadata ) {
else if ( metadata["cull mode"].as<uf::stl::string>() == "none" ) cullMode = VK_CULL_MODE_NONE;
else if ( metadata["cull mode"].as<uf::stl::string>() == "both" ) cullMode = VK_CULL_MODE_FRONT_AND_BACK;
}
// to-do: probably parse depth op/min/max
if ( ext::json::isObject(metadata["depth bias"]) ) {
depth.bias.enable = VK_TRUE;
depth.bias.constant = metadata["depth bias"]["constant"].as<float>();

View File

@ -110,149 +110,97 @@ void ext::vulkan::BaseRenderMode::tick() {
}
}
void ext::vulkan::BaseRenderMode::render() {
// if ( ext::vulkan::states::frameSkip ) return;
// if ( ext::vulkan::renderModes.size() > 1 ) return;
// if ( ext::vulkan::renderModes.back() != this ) return;
// if ( this->commands.container().empty() ) return;
if ( this->commands.container().empty() ) return;
//lockMutex( this->mostRecentCommandPoolId );
auto& commands = getCommands( this->mostRecentCommandPoolId );
uint32_t imageIndex;
VK_CHECK_RESULT(vkWaitForFences(*device, 1, &fences[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT));
VK_CHECK_RESULT(swapchain.acquireNextImage(&imageIndex, swapchain.presentCompleteSemaphores[states::currentBuffer]));
VK_CHECK_RESULT(vkResetFences(*device, 1, &fences[states::currentBuffer]));
VkPipelineStageFlags waitStageMask[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = waitStageMask;
submitInfo.pWaitSemaphores = &swapchain.presentCompleteSemaphores[states::currentBuffer];
submitInfo.waitSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &renderCompleteSemaphores[imageIndex];
submitInfo.signalSemaphoreCount = 1;
submitInfo.pCommandBuffers = &commands[states::currentBuffer];
submitInfo.commandBufferCount = 1;
{
VkQueue queue = device->getQueue( QueueEnum::GRAPHICS );
VkResult res = vkQueueSubmit( queue, 1, &submitInfo, fences[states::currentBuffer]);
VK_CHECK_QUEUE_CHECKPOINT( queue, res );
}
VK_CHECK_RESULT(swapchain.queuePresent(device->getQueue( QueueEnum::PRESENT ), imageIndex, renderCompleteSemaphores[imageIndex]));
#if 0
auto& commands = getCommands( this->mostRecentCommandPoolId );
auto& commandBuffer = commands[states::currentBuffer];
vkResetCommandBuffer(commandBuffer, 0);
{
VkQueue queue = device->getQueue( QueueEnum::PRESENT );
VkResult res = vkQueueWaitIdle(device->getQueue( QueueEnum::PRESENT ));
VK_CHECK_QUEUE_CHECKPOINT( queue, res );
}
#endif
states::currentBuffer = (states::currentBuffer + 1) % ext::vulkan::swapchain.buffers;
this->executed = true;
//unlockMutex( this->mostRecentCommandPoolId );
}
void ext::vulkan::BaseRenderMode::destroy() {
ext::vulkan::RenderMode::destroy();
for ( auto& presentCompleteSemaphore : swapchain.presentCompleteSemaphores ) {
vkDestroySemaphore( *device, presentCompleteSemaphore, nullptr);
VK_UNREGISTER_HANDLE( presentCompleteSemaphore );
}
swapchain.presentCompleteSemaphores.clear();
}
ext::vulkan::GraphicDescriptor ext::vulkan::BaseRenderMode::bindGraphicDescriptor( const ext::vulkan::GraphicDescriptor& reference, size_t pass ) {
ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass);
descriptor.depth.test = false;
descriptor.depth.write = false;
return descriptor;
}
void ext::vulkan::BaseRenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {
// if ( ext::vulkan::renderModes.size() > 1 ) return;
auto windowSize = device->window->getSize();
float width = windowSize.x; //this->width > 0 ? this->width : windowSize.x;
float height = windowSize.y; //this->height > 0 ? this->height : windowSize.y;
VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo();
cmdBufInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED
imageMemoryBarrier.subresourceRange.baseMipLevel = 0;
imageMemoryBarrier.subresourceRange.levelCount = 1;
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
imageMemoryBarrier.subresourceRange.layerCount = 1;
imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
uf::stl::vector<RenderMode*> layers = ext::vulkan::getRenderModes(uf::stl::vector<uf::stl::string>{"Deferred", "Compute:RT", "RenderTarget"}, false);
#if 0
if ( settings::pipelines::rt ) {
std::reverse( layers.begin(), layers.end() );
}
#endif
auto& scene = uf::scene::getCurrentScene();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
auto& commands = getCommands();
uf::stl::vector<VkClearValue> clearValues;
for ( auto& attachment : renderTarget.attachments ) {
pod::Vector4f clearColor = uf::vector::decode( sceneMetadataJson["system"]["renderer"]["clear values"][(int) clearValues.size()], pod::Vector4f{0, 0, 0, 0} );
auto& clearValue = clearValues.emplace_back();
if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
clearValue.color.float32[0] = clearColor[0];
clearValue.color.float32[1] = clearColor[1];
clearValue.color.float32[2] = clearColor[2];
clearValue.color.float32[3] = clearColor[3];
} else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
if ( uf::matrix::reverseInfiniteProjection ) {
clearValue.depthStencil = { 0.0f, 0 };
} else {
clearValue.depthStencil = { 1.0f, 0 };
STATIC_THREAD_LOCAL(uf::stl::vector<ext::vulkan::Graphic*>, graphics);
auto& scene = uf::scene::getCurrentScene();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
auto/*&*/ graph = scene.getGraph();
for ( auto entity : graph ) {
if ( entity->hasComponent<ext::vulkan::Graphics>() ) {
auto& g = entity->getComponent<ext::vulkan::Graphics>();
for ( auto& [ _, graphic ] : g ) {
if ( !graphic.initialized || !graphic.process ) continue;
graphics.emplace_back(&graphic);
}
}
if ( entity->hasComponent<ext::vulkan::Graphic>() ) {
auto& graphic = entity->getComponent<ext::vulkan::Graphic>();
if ( !graphic.initialized || !graphic.process ) continue;
graphics.emplace_back(&graphic);
}
}
}
VkRenderPassBeginInfo renderPassBeginInfo = {};
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassBeginInfo.pNext = nullptr;
renderPassBeginInfo.renderPass = renderTarget.renderPass;
renderPassBeginInfo.renderArea.offset.x = 0;
renderPassBeginInfo.renderArea.offset.y = 0;
renderPassBeginInfo.renderArea.extent.width = width;
renderPassBeginInfo.renderArea.extent.height = height;
renderPassBeginInfo.clearValueCount = clearValues.size();
renderPassBeginInfo.pClearValues = &clearValues[0];
size_t frame = states::currentBuffer;
auto windowSize = device->window->getSize();
float width = windowSize.x; //this->width > 0 ? this->width : windowSize.x;
float height = windowSize.y; //this->height > 0 ? this->height : windowSize.y;
// Update dynamic viewport state
VkViewport viewport = {};
viewport.width = (float) width;
viewport.height = (float) height;
viewport.minDepth = (float) 0.0f;
viewport.maxDepth = (float) 1.0f;
// Update dynamic scissor state
VkRect2D scissor = {};
scissor.extent.width = width;
scissor.extent.height = height;
scissor.offset.x = 0;
scissor.offset.y = 0;
for (size_t frame = 0; frame < commands.size(); ++frame) {
VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo();
cmdBufInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED
imageMemoryBarrier.subresourceRange.baseMipLevel = 0;
imageMemoryBarrier.subresourceRange.levelCount = 1;
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
imageMemoryBarrier.subresourceRange.layerCount = 1;
imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
uf::stl::vector<RenderMode*> layers = ext::vulkan::getRenderModes(uf::stl::vector<uf::stl::string>{"Deferred", "Compute:RT", "RenderTarget"}, false);
float depthClear = uf::matrix::reverseInfiniteProjection ? 0.0f : 1.0f;
uf::stl::vector<VkClearValue> clearValues;
for ( auto& attachment : renderTarget.attachments ) {
pod::Vector4f clearColor = uf::vector::decode( sceneMetadataJson["system"]["renderer"]["clear values"][(int) clearValues.size()], pod::Vector4f{0, 0, 0, 0} );
auto& clearValue = clearValues.emplace_back();
if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
clearValue.color.float32[0] = clearColor[0];
clearValue.color.float32[1] = clearColor[1];
clearValue.color.float32[2] = clearColor[2];
clearValue.color.float32[3] = clearColor[3];
} else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
clearValue.depthStencil = { depthClear, 0 };
}
}
VkRenderPassBeginInfo renderPassBeginInfo = {};
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassBeginInfo.pNext = nullptr;
renderPassBeginInfo.renderPass = renderTarget.renderPass;
renderPassBeginInfo.renderArea.offset.x = 0;
renderPassBeginInfo.renderArea.offset.y = 0;
renderPassBeginInfo.renderArea.extent.width = width;
renderPassBeginInfo.renderArea.extent.height = height;
renderPassBeginInfo.clearValueCount = clearValues.size();
renderPassBeginInfo.pClearValues = &clearValues[0];
// Update dynamic viewport state
VkViewport viewport = {};
viewport.width = (float) width;
viewport.height = (float) height;
viewport.minDepth = (float) 0.0f;
viewport.maxDepth = (float) 1.0f;
auto& commandBuffer = commands[frame];
renderPassBeginInfo.framebuffer = renderTarget.framebuffers[frame];
// Update dynamic scissor state
VkRect2D scissor = {};
scissor.extent.width = width;
scissor.extent.height = height;
scissor.offset.x = 0;
scissor.offset.y = 0;
renderPassBeginInfo.framebuffer = renderTarget.framebuffers[imageIndex];
VK_CHECK_RESULT(vkBeginCommandBuffer(commandBuffer, &cmdBufInfo));
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::BEGIN, "begin" );
@ -295,6 +243,52 @@ void ext::vulkan::BaseRenderMode::createCommandBuffers( const uf::stl::vector<ex
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::END, "end" );
VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer));
}
VkPipelineStageFlags waitStageMask[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = waitStageMask;
submitInfo.pWaitSemaphores = &swapchain.presentCompleteSemaphores[states::currentBuffer];
submitInfo.waitSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &renderCompleteSemaphores[imageIndex];
submitInfo.signalSemaphoreCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
submitInfo.commandBufferCount = 1;
{
VkQueue queue = device->getQueue( QueueEnum::GRAPHICS );
VkResult res = vkQueueSubmit( queue, 1, &submitInfo, fences[states::currentBuffer]);
VK_CHECK_QUEUE_CHECKPOINT( queue, res );
}
VK_CHECK_RESULT(swapchain.queuePresent(device->getQueue( QueueEnum::PRESENT ), imageIndex, renderCompleteSemaphores[imageIndex]));
states::currentBuffer = (states::currentBuffer + 1) % ext::vulkan::swapchain.buffers;
this->executed = true;
}
void ext::vulkan::BaseRenderMode::destroy() {
ext::vulkan::RenderMode::destroy();
for ( auto& presentCompleteSemaphore : swapchain.presentCompleteSemaphores ) {
vkDestroySemaphore( *device, presentCompleteSemaphore, nullptr);
VK_UNREGISTER_HANDLE( presentCompleteSemaphore );
}
swapchain.presentCompleteSemaphores.clear();
}
ext::vulkan::GraphicDescriptor ext::vulkan::BaseRenderMode::bindGraphicDescriptor( const ext::vulkan::GraphicDescriptor& reference, size_t pass ) {
ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass);
descriptor.depth.test = false;
descriptor.depth.write = false;
return descriptor;
}
void ext::vulkan::BaseRenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {
}
#endif

View File

@ -415,7 +415,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
shader.aliasAttachment("scratch", this, VK_IMAGE_LAYOUT_GENERAL);
// atomic counter buffer
::postprocesses::bloom.atomicCounter.initialize( (const void*) nullptr, sizeof(::AtomicCounter) * 1, uf::renderer::enums::Buffer::STORAGE );
::postprocesses::bloom.atomicCounter.initialize( (const void*) nullptr, sizeof(::AtomicCounter) * 1, uf::renderer::enums::Buffer::STORAGE | VK_BUFFER_USAGE_TRANSFER_DST_BIT );
shader.aliasBuffer("atomicCounterBloom", ::postprocesses::bloom.atomicCounter);
}
@ -449,7 +449,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
shader.aliasAttachment("scratch", this, VK_IMAGE_LAYOUT_GENERAL);
// atomic counter buffer
::postprocesses::dof.atomicCounter.initialize( (const void*) nullptr, sizeof(::AtomicCounter) * 1, uf::renderer::enums::Buffer::STORAGE );
::postprocesses::dof.atomicCounter.initialize( (const void*) nullptr, sizeof(::AtomicCounter) * 1, uf::renderer::enums::Buffer::STORAGE | VK_BUFFER_USAGE_TRANSFER_DST_BIT );
shader.aliasBuffer("atomicCounterBloom", ::postprocesses::dof.atomicCounter);
}
@ -482,7 +482,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
shader.aliasAttachment("depth_resolved", this);
// atomic counter buffer
::postprocesses::depthPyramid.atomicCounter.initialize( (const void*) nullptr, sizeof(::AtomicCounter) * 1, uf::renderer::enums::Buffer::STORAGE );
::postprocesses::depthPyramid.atomicCounter.initialize( (const void*) nullptr, sizeof(::AtomicCounter) * 1, uf::renderer::enums::Buffer::STORAGE | VK_BUFFER_USAGE_TRANSFER_DST_BIT );
shader.aliasBuffer("atomicCounterDepth", ::postprocesses::depthPyramid.atomicCounter);
}
}
@ -759,6 +759,15 @@ void ext::vulkan::DeferredRenderMode::destroy() {
ext::vulkan::GraphicDescriptor ext::vulkan::DeferredRenderMode::bindGraphicDescriptor( const ext::vulkan::GraphicDescriptor& reference, size_t pass ) {
ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass);
if ( descriptor.renderMode != "" ) descriptor.invalidated = true;
if ( metadata.json["reverse depth"].as<bool>(uf::matrix::reverseInfiniteProjection) ) {
descriptor.depth.operation = ext::vulkan::enums::Compare::GREATER_OR_EQUAL;
descriptor.depth.min = 1.0f;
descriptor.depth.max = 0.0f;
} else {
descriptor.depth.operation = ext::vulkan::enums::Compare::LESS;
descriptor.depth.min = 0.0f;
descriptor.depth.max = 1.0f;
}
return descriptor;
}
void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {
@ -783,7 +792,13 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
auto& commands = getCommands();
// auto& swapchainRender = ext::vulkan::getRenderMode("Swapchain");
float depthClear = uf::matrix::reverseInfiniteProjection ? 0.0f : 1.0f;
for ( auto graphic : graphics ) {
auto descriptor = bindGraphicDescriptor(graphic->descriptor);
depthClear = descriptor.depth.max;
break;
}
uf::stl::vector<VkClearValue> clearValues;
for ( auto& attachment : renderTarget.attachments ) {
pod::Vector4f clearColor = uf::vector::decode( sceneMetadataJson["system"]["renderer"]["clear values"][(int) clearValues.size()], pod::Vector4f{0, 0, 0, 0} );
@ -794,11 +809,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
clearValue.color.float32[2] = clearColor[2];
clearValue.color.float32[3] = clearColor[3];
} else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
if ( uf::matrix::reverseInfiniteProjection ) {
clearValue.depthStencil = { 0.0f, 0 };
} else {
clearValue.depthStencil = { 1.0f, 0 };
}
clearValue.depthStencil = { depthClear, 0 };
}
}
bool shouldRecord = true; // ( settings::pipelines::rt && !uf::config["engine"]["scenes"]["rt"]["full"].as<bool>() ) || !settings::pipelines::rt;
@ -998,7 +1009,8 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
if ( graphic->descriptor.renderMode != this->getName() ) continue;
if ( graphic->descriptor.renderTarget != 1 /*"forward"*/ ) continue;
//if ( graphic->descriptor.pipeline != "forward" ) continue;
ext::vulkan::GraphicDescriptor descriptor = graphic->descriptor; // bindGraphicDescriptor(graphic->descriptor, currentSubpass);
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass);
//descriptor.renderTarget = 1;
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, ::fmt::format("graphic[{}]", currentDraw) );
graphic->record( commandBuffer, descriptor, 0, currentDraw++, frame );
}

View File

@ -25,8 +25,15 @@ ext::vulkan::GraphicDescriptor ext::vulkan::RenderTargetRenderMode::bindGraphicD
descriptor.depth.write = false;
} else if ( metadata.type == "depth" ) {
descriptor.cullMode = VK_CULL_MODE_NONE;
// descriptor.depth.test = false;
// descriptor.depth.write = false;
if ( metadata.json["reverse depth"].as<bool>(uf::matrix::reverseInfiniteProjection) ) {
descriptor.depth.operation = ext::vulkan::enums::Compare::GREATER_OR_EQUAL;
descriptor.depth.min = 1.0f;
descriptor.depth.max = 0.0f;
} else {
descriptor.depth.operation = ext::vulkan::enums::Compare::LESS;
descriptor.depth.min = 0.0f;
descriptor.depth.max = 1.0f;
}
}
return descriptor;
}
@ -321,16 +328,18 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
uf::stl::vector<VkClearValue> clearValues;
float depthClear = uf::matrix::reverseInfiniteProjection ? 0.0f : 1.0f;
for ( auto graphic : graphics ) {
auto descriptor = bindGraphicDescriptor(graphic->descriptor);
depthClear = descriptor.depth.max;
break;
}
for ( auto& attachment : renderTarget.attachments ) {
auto& clearValue = clearValues.emplace_back();
if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
clearValue.color = { { 0.0f, 0.0f, 0.0f, 0.0f } };
} else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
if ( uf::matrix::reverseInfiniteProjection ) {
clearValue.depthStencil = { 0.0f, 0 };
} else {
clearValue.depthStencil = { 1.0f, 0 };
}
clearValue.depthStencil = { depthClear, 0 };
}
}

View File

@ -15,8 +15,6 @@
#define VK_DEBUG_VALIDATION_MESSAGE(...)\
//VK_VALIDATION_MESSAGE(__VA_ARGS__);
#define IS_DYNAMIC(name) true // name == "UBO"
#define UF_SHADER_PARSE_AS_JSON 0
#if UF_SHADER_PARSE_AS_JSON
ext::json::Value ext::vulkan::definitionToJson(/*const*/ ext::json::Value& definition ) {
@ -519,11 +517,9 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
.size = bufferSize,
};
if ( descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ) {
if ( IS_DYNAMIC(name) ) {
UF_MSG_DEBUG("Registered dynamic UBO: {}", name);
}
metadata.dynamicRanges.emplace_back( IS_DYNAMIC(name) ? bufferSize : 0 );
if ( IS_DYNAMIC(name) ) {
descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
metadata.dynamicRanges.emplace_back( bufferSize );
}
} break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
@ -580,7 +576,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
LOOP_RESOURCES( storage_images, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE );
LOOP_RESOURCES( separate_samplers, VK_DESCRIPTOR_TYPE_SAMPLER );
LOOP_RESOURCES( subpass_inputs, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT );
LOOP_RESOURCES( uniform_buffers, VK_UBO_USE_N_BUFFERS ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER );
LOOP_RESOURCES( uniform_buffers, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER );
LOOP_RESOURCES( storage_buffers, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER );
LOOP_RESOURCES( acceleration_structures, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR );
#undef LOOP_RESOURCES

View File

@ -20,7 +20,7 @@ pod::Vector3f uf::camera::eye( const pod::Camera& camera, int i ) {
return position;
}
void uf::camera::view( pod::Camera& camera, const pod::Matrix4f& mat, int i ) {
if ( i < 0 ) i = uf::camera::maxViews; // camera.viewport.views;
if ( i < 0 ) i = uf::camera::maxViews; // camera.views;
if ( i >= uf::camera::maxViews ) {
for ( i = 0; i < uf::camera::maxViews; ++i ) {
camera.viewport.matrices[i].view = mat;
@ -30,7 +30,7 @@ void uf::camera::view( pod::Camera& camera, const pod::Matrix4f& mat, int i ) {
camera.viewport.matrices[i].view = mat;
}
void uf::camera::projection( pod::Camera& camera, const pod::Matrix4f& mat, int i ) {
if ( i < 0 ) i = uf::camera::maxViews; // camera.viewport.views;
if ( i < 0 ) i = uf::camera::maxViews; // camera.views;
if ( i >= uf::camera::maxViews ) {
for ( i = 0; i < uf::camera::maxViews; ++i ) camera.viewport.matrices[i].projection = mat;
return;
@ -78,15 +78,15 @@ const pod::Matrix4& uf::Camera::getProjection( size_t i ) const { return this->v
void uf::Camera::setStereoscopic( bool b ) { this->stereoscopic = b; }
pod::Vector3f uf::Camera::getEye( size_t i ) const {
if ( i < 0 ) i = uf::camera::maxViews; // this->viewport.views;
if ( i < 0 ) i = uf::camera::maxViews; // this->views;
return uf::camera::eye( *this, i );
}
void uf::Camera::setView( const pod::Matrix4& mat, int i ) {
if ( i < 0 ) i = uf::camera::maxViews; // this->viewport.views;
if ( i < 0 ) i = uf::camera::maxViews; // this->views;
uf::camera::view( *this, mat, i );
}
void uf::Camera::setProjection( const pod::Matrix4& mat, int i ) {
if ( i < 0 ) i = uf::camera::maxViews; // this->viewport.views;
if ( i < 0 ) i = uf::camera::maxViews; // this->views;
uf::camera::projection( *this, mat, i );
}
void uf::Camera::update() {