VK_KHR_multiview support (but it broke VXGI)

This commit is contained in:
ecker 2026-05-11 20:56:16 -05:00
parent 2e018962ee
commit 2475605941
13 changed files with 235 additions and 306 deletions

View File

@ -8,7 +8,7 @@
"useLightmaps": false,
"max": 32,
"shadows": {
"enabled": true, // to-do: fix
"enabled": true,
"update": 4,
"max": 16,
"samples": 2
@ -67,9 +67,9 @@
"vulkan": {
"version": 1.3,
"validation": {
"enabled": false,
"messages": false,
"checkpoints": false,
"enabled": true,
"messages": true,
"checkpoints": true,
"filters": [
// "0xe5d1743c" // VUID-vkCmdDispatch-None-02699 (problem when using VXGI) (seems to be fixed?)
// ,"0x6714bd0c" // VUID-vkCmdDispatch-format-07753 (for some dumb shit) (seems to be fixed?)
@ -169,10 +169,14 @@
,"VK_KHR_get_memory_requirements2"
,"VK_KHR_bind_memory2"
,"VK_KHR_dedicated_allocation"
,"VK_KHR_multiview"
]
},
"features": [
"nullDescriptor"
// 1.1
"multiview"
//
,"nullDescriptor"
,"fragmentStoresAndAtomics"
,"geometryShader"
,"multiViewport"
@ -192,7 +196,10 @@
,"bufferDeviceAddress"
],
"featureChain": [
"physicalDevice2"
// 1.1
"physicalDeviceVulkan11"
//
,"physicalDevice2"
,"shaderDrawParameters"
,"robustness"
,"shaderClock"
@ -303,7 +310,7 @@
"enabled": false
},
"fsr": {
"enabled": true,
"enabled": false,
"upscale": true,
"interpolation": true, // it works but i don't think it's presenting the frame
"sharpness": 0,

View File

@ -26,33 +26,33 @@ layout (constant_id = 1) const uint CUBEMAPS = 128;
#endif
#if !MULTISAMPLING
layout(binding = 0) uniform utexture2D samplerId;
layout(binding = 0) uniform utexture2DArray samplerId;
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
layout(binding = 1) uniform texture2D samplerBary;
layout(binding = 1) uniform texture2DArray samplerBary;
#endif
#else
layout(binding = 1) uniform texture2D samplerUv;
layout(binding = 2) uniform texture2D samplerNormal;
layout(binding = 1) uniform texture2DArray samplerUv;
layout(binding = 2) uniform texture2DArray samplerNormal;
#endif
layout(binding = 3) uniform texture2D samplerDepth;
layout(binding = 3) uniform texture2DArray samplerDepth;
#else
layout(binding = 0) uniform utexture2DMS samplerId;
layout(binding = 0) uniform utexture2DMSArray samplerId;
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
layout(binding = 1) uniform texture2DMS samplerBary;
layout(binding = 1) uniform texture2DMSArray samplerBary;
#endif
#else
layout(binding = 1) uniform texture2DMS samplerUv;
layout(binding = 2) uniform texture2DMS samplerNormal;
layout(binding = 1) uniform texture2DMSArray samplerUv;
layout(binding = 2) uniform texture2DMSArray samplerNormal;
#endif
layout(binding = 3) uniform texture2DMS samplerDepth;
layout(binding = 3) uniform texture2DMSArray samplerDepth;
#endif
layout(binding = 7, rgba16f) uniform writeonly image2D imageColor;
layout(binding = 8, rgba16f) uniform writeonly image2D imageBright;
layout(binding = 9, rg16f) uniform writeonly image2D imageMotion;
layout(binding = 7, rgba16f) uniform writeonly image2DArray imageColor;
layout(binding = 8, rgba16f) uniform writeonly image2DArray imageBright;
layout(binding = 9, rg16f) uniform writeonly image2DArray imageMotion;
layout( push_constant ) uniform PushBlock {
uint pass;
@ -132,12 +132,12 @@ layout (binding = 20) uniform sampler3D samplerNoise;
#endif
#if MULTISAMPLING
#define IMAGE_LOAD(X) texelFetch( X, ivec2(gl_GlobalInvocationID.xy), msaa.currentID )
#define IMAGE_LOAD(X) texelFetch( X, ivec3(gl_GlobalInvocationID.xyz), msaa.currentID )
#else
#define IMAGE_LOAD(X) texelFetch( X, ivec2(gl_GlobalInvocationID.xy), 0 )
#define IMAGE_LOAD(X) texelFetch( X, ivec3(gl_GlobalInvocationID.xyz), 0 )
#endif
#define IMAGE_STORE(X, Y) imageStore( X, ivec2(gl_GlobalInvocationID.xy), Y )
#define IMAGE_STORE(X, Y) imageStore( X, ivec3(gl_GlobalInvocationID.xyz), Y )
bool USE_SKYBOX_ON_DIVERGENCE = false;
@ -158,7 +158,7 @@ void postProcess() {
vec2 outFragMotion = surface.motion;
if ( ubo.settings.mode.type > 0x0000 ) {
uvec2 renderSize = imageSize(imageColor);
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);
@ -180,10 +180,10 @@ void postProcess() {
}
void populateSurface() {
const uvec2 renderSize = imageSize(imageColor);
if ( gl_GlobalInvocationID.x >= renderSize.x || gl_GlobalInvocationID.y >= renderSize.y || gl_GlobalInvocationID.z > PushConstant.pass ) return;
const uvec2 renderSize = imageSize(imageColor).xy;
if ( gl_GlobalInvocationID.x >= renderSize.x || gl_GlobalInvocationID.y >= renderSize.y /*|| gl_GlobalInvocationID.z > PushConstant.pass*/ ) return;
surface.pass = PushConstant.pass;
surface.pass = gl_GlobalInvocationID.z;
surface.fragment = vec4(0);
surface.light = vec4(0);
surface.motion = vec2(0);

View File

@ -1,5 +1,6 @@
layout (constant_id = 0) const uint PASSES = 6;
#extension GL_ARB_shader_draw_parameters : enable
#extension GL_EXT_multiview : enable
#include "../../common/macros.h"
#include "../../common/structs.h"
@ -73,8 +74,8 @@ void main() {
const mat4 view = mat4(1);
const mat4 projection = mat4(1);
#else
const mat4 view = camera.viewport[PushConstant.pass].view;
const mat4 projection = camera.viewport[PushConstant.pass].projection;
const mat4 view = camera.viewport[/*PushConstant.pass*/gl_ViewIndex].view;
const mat4 projection = camera.viewport[/*PushConstant.pass*/gl_ViewIndex].projection;
#endif
#if SKINNED
const mat4 skinned = joints.length() <= 0 || jointID < 0 ? mat4(1.0) : inWeights.x * joints[jointID + int(inJoints.x)] + inWeights.y * joints[jointID + int(inJoints.y)] + inWeights.z * joints[jointID + int(inJoints.z)] + inWeights.w * joints[jointID + int(inJoints.w)];
@ -93,7 +94,7 @@ void main() {
outPOS0 = gl_Position;
outPOS1 = gl_Position;
outId = uvec4(triangleID, drawID, instanceID, PushConstant.pass);
outId = uvec4(triangleID, drawID, instanceID, /*PushConstant.pass*/gl_ViewIndex);
outPosition = vec3(model * vec4(inPos.xyz, 1.0));
outUv = inUv;

View File

@ -1,5 +1,6 @@
#version 450
#pragma shader_stage(geometry)
#extension GL_EXT_multiview : require
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
@ -56,7 +57,7 @@ void main(){
A = N.z > N[A] ? 2 : A;
#endif
const uint CASCADE = inId[0].w;
const uint CASCADE = gl_ViewIndex; // inId[0].w;
const float power = cascadePower(CASCADE);
vec3 P[3] = {
vec3( ubo.voxel * vec4( inPosition[0], 1 ) ) / power,
@ -77,6 +78,7 @@ void main(){
outNormal = inNormal[i];
outTangent = inTangent[i];
outId = inId[i];
outId.w = gl_ViewIndex;
const vec3 P = outPosition; // + D;
#if USE_CROSS

View File

@ -23,6 +23,7 @@ namespace ext {
VkImage image;
VkDeviceMemory mem;
VkImageView view;
VkImageView framebufferView;
uf::stl::vector<VkImageView> views;
VmaAllocation allocation;
VmaAllocationInfo allocationInfo;

View File

@ -23,6 +23,7 @@
#define VK_DEFAULT_DEFER_BUFFER_DESTROY ext::vulkan::settings::defaultDeferBufferDestroy
#define VK_DEFAULT_COMMAND_BUFFER_IMMEDIATE ext::vulkan::settings::defaultCommandBufferImmediate
#define VK_UBO_USE_N_BUFFERS 0
#define VK_USE_MULTIVIEW 1
namespace ext {
namespace vulkan {

View File

@ -78,7 +78,7 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
if ( metadataJson["light"]["type"].as<uf::stl::string>() == "point" ) {
metadataJson["light"]["fov"] = 90.0f;
renderMode.metadata.subpasses = 6;
renderMode.metadata.views = 6;
}
float fov = metadataJson["light"]["fov"].as<float>(90) * (3.14159265358f / 180.0f);

View File

@ -131,7 +131,8 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
}
renderMode.metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::vxgi);
renderMode.metadata.samples = 1;
renderMode.metadata.subpasses = metadata.cascades;
// renderMode.metadata.subpasses = metadata.cascades;
renderMode.renderTarget.views = metadata.cascades;
renderMode.width = metadata.fragmentSize.x;
renderMode.height = metadata.fragmentSize.y;

View File

@ -378,6 +378,58 @@ namespace {
return json;
}
void enableRequestedDeviceFeatures11( VkPhysicalDeviceVulkan11Features& features, VkPhysicalDeviceVulkan11Features& enabledFeatures ) {
ext::json::Value json;
#define CHECK_FEATURE( NAME )\
if ( feature == #NAME ) {\
if ( features.NAME == VK_TRUE ) {\
enabledFeatures.NAME = true;\
VK_VALIDATION_MESSAGE("Enabled feature: {}", feature);\
} else VK_VALIDATION_MESSAGE("Failed to enable feature: {}", feature);\
}
for ( auto& feature : ext::vulkan::settings::requested::deviceFeatures ) {
CHECK_FEATURE(storageBuffer16BitAccess);
CHECK_FEATURE(uniformAndStorageBuffer16BitAccess);
CHECK_FEATURE(storagePushConstant16);
CHECK_FEATURE(storageInputOutput16);
CHECK_FEATURE(multiview);
CHECK_FEATURE(multiviewGeometryShader);
CHECK_FEATURE(multiviewTessellationShader);
CHECK_FEATURE(variablePointersStorageBuffer);
CHECK_FEATURE(variablePointers);
CHECK_FEATURE(protectedMemory);
CHECK_FEATURE(samplerYcbcrConversion);
CHECK_FEATURE(shaderDrawParameters);
}
#undef CHECK_FEATURE
}
ext::json::Value retrieveDeviceFeatures11( ext::vulkan::Device& device, VkPhysicalDeviceVulkan11Features& features, VkPhysicalDeviceVulkan11Features& enabledFeatures ) {
ext::json::Value json;
#define CHECK_FEATURE( NAME )\
json[#NAME]["supported"] = features.NAME;\
json[#NAME]["enabled"] = enabledFeatures.NAME;
CHECK_FEATURE(storageBuffer16BitAccess);
CHECK_FEATURE(uniformAndStorageBuffer16BitAccess);
CHECK_FEATURE(storagePushConstant16);
CHECK_FEATURE(storageInputOutput16);
CHECK_FEATURE(multiview);
CHECK_FEATURE(multiviewGeometryShader);
CHECK_FEATURE(multiviewTessellationShader);
CHECK_FEATURE(variablePointersStorageBuffer);
CHECK_FEATURE(variablePointers);
CHECK_FEATURE(protectedMemory);
CHECK_FEATURE(samplerYcbcrConversion);
CHECK_FEATURE(shaderDrawParameters);
#undef CHECK_FEATURE
return json;
}
void enableRequestedDeviceFeatures12( VkPhysicalDeviceVulkan12Features& features, VkPhysicalDeviceVulkan12Features& enabledFeatures ) {
ext::json::Value json;
@ -1185,6 +1237,7 @@ void ext::vulkan::Device::initialize() {
std::queue<void*> chain = {};
VkPhysicalDeviceFeatures2 physicalDeviceFeatures2{};
VkPhysicalDeviceVulkan11Features physicalDeviceVulkan11Features{};
VkPhysicalDeviceVulkan12Features physicalDeviceVulkan12Features{};
VkPhysicalDeviceDescriptorIndexingFeatures descriptorIndexingFeatures{};
VkPhysicalDeviceBufferDeviceAddressFeatures bufferDeviceAddressFeatures{};
@ -1197,12 +1250,16 @@ void ext::vulkan::Device::initialize() {
VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR fragmentShaderBarycentricFeatures{};
VkPhysicalDeviceSubgroupSizeControlFeatures subgroupSizeControlFeatures{};
VkPhysicalDeviceFeatures2 enabledDeviceFeatures2{};
VkPhysicalDeviceVulkan11Features enabledPhysicalDeviceVulkan11Features{};
VkPhysicalDeviceVulkan12Features enabledPhysicalDeviceVulkan12Features{};
VkPhysicalDeviceFeatures2 enabledDeviceFeatures2{}; {
{
enabledDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
enabledPhysicalDeviceVulkan11Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
enabledPhysicalDeviceVulkan12Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
enabledDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
enabledDeviceFeatures2.pNext = &enabledPhysicalDeviceVulkan12Features;
enabledPhysicalDeviceVulkan11Features.pNext = &enabledPhysicalDeviceVulkan12Features;
enabledDeviceFeatures2.pNext = &enabledPhysicalDeviceVulkan11Features;
vkGetPhysicalDeviceFeatures2(device.physicalDevice, &enabledDeviceFeatures2);
}
@ -1213,6 +1270,20 @@ void ext::vulkan::Device::initialize() {
chain.push( &physicalDeviceFeatures2 );
VK_VALIDATION_MESSAGE("Enabled feature chain: {}", "physicalDeviceFeatures2" );
}
if ( ext::vulkan::settings::requested::featureChain["physicalDeviceVulkan11"].as<bool>(false) ) {
physicalDeviceVulkan11Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
enableRequestedDeviceFeatures11( enabledPhysicalDeviceVulkan11Features, physicalDeviceVulkan11Features );
chain.push( &physicalDeviceVulkan11Features );
VK_VALIDATION_MESSAGE("Enabled feature chain: {}", "physicalDeviceVulkan11Features" );
} else {
// Only add the standalone extension struct if we ARE NOT using the Vulkan 1.1 core struct!
if ( ext::vulkan::settings::requested::featureChain["shaderDrawParameters"].as<bool>(false) ) {
shaderDrawParametersFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES;
shaderDrawParametersFeatures.shaderDrawParameters = VK_TRUE;
chain.push( &shaderDrawParametersFeatures );
VK_VALIDATION_MESSAGE("Enabled feature chain: {}", "shaderDrawParametersFeatures" );
}
}
if ( ext::vulkan::settings::requested::featureChain["physicalDeviceVulkan12"].as<bool>(false) ) {
physicalDeviceVulkan12Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
enableRequestedDeviceFeatures12( enabledPhysicalDeviceVulkan12Features, physicalDeviceVulkan12Features );
@ -1239,12 +1310,6 @@ void ext::vulkan::Device::initialize() {
}
//
if ( ext::vulkan::settings::requested::featureChain["shaderDrawParameters"].as<bool>(false) ) {
shaderDrawParametersFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES;
shaderDrawParametersFeatures.shaderDrawParameters = VK_TRUE;
chain.push( &shaderDrawParametersFeatures );
VK_VALIDATION_MESSAGE("Enabled feature chain: {}", "shaderDrawParametersFeatures" );
}
if ( ext::vulkan::settings::requested::featureChain["robustness"].as<bool>(false) ) {
robustnessFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
robustnessFeatures.nullDescriptor = VK_TRUE;

View File

@ -205,46 +205,42 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
metadata.attachments["output"] = attachments.color;
// First pass: fill the G-Buffer
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
renderTarget.addPass(
/*.*/ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
/*.colors =*/ { attachments.id, attachments.bary },
#else
/*.colors =*/ { attachments.id },
#endif
#else
/*.colors =*/ { attachments.id, attachments.uv, attachments.normal },
#endif
/*.inputs =*/ {},
/*.resolve =*/{},
/*.depth = */ attachments.depth,
/*.layer = */0,
/*.autoBuildPipeline =*/ true
);
if ( DEFERRED_MODE == "fragment" ) {
renderTarget.addPass(
/*.*/ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
/*.*/ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
/*.colors =*/ { attachments.color, attachments.scratch, attachments.motion },
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
/*.colors =*/ { attachments.id, attachments.bary },
/*.inputs =*/ { attachments.id, attachments.depth, attachments.bary },
#else
/*.colors =*/ { attachments.id },
/*.inputs =*/ { attachments.id, attachments.depth },
#endif
#else
/*.colors =*/ { attachments.id, attachments.uv, attachments.normal },
/*.inputs =*/ { attachments.id, attachments.depth, attachments.uv, attachments.normal },
#endif
/*.inputs =*/ {},
/*.resolve =*/{},
/*.depth = */ attachments.depth,
/*.layer = */eye,
/*.autoBuildPipeline =*/ true
/*.depth = */attachments.depth,
/*.layer = */0,
/*.autoBuildPipeline =*/ false
);
}
if ( DEFERRED_MODE == "fragment" ) {
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
renderTarget.addPass(
/*.*/ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
/*.colors =*/ { attachments.color, attachments.scratch, attachments.motion },
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
/*.inputs =*/ { attachments.id, attachments.depth, attachments.bary },
#else
/*.inputs =*/ { attachments.id, attachments.depth },
#endif
#else
/*.inputs =*/ { attachments.id, attachments.depth, attachments.uv, attachments.normal },
#endif
/*.resolve =*/{},
/*.depth = */attachments.depth,
/*.layer = */eye,
/*.autoBuildPipeline =*/ false
);
}
}
// metadata.outputs.emplace_back(metadata.attachments["output"]);
renderTarget.initialize( device );
@ -818,7 +814,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
// render to geometry buffers
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
{
size_t currentPass = 0;
size_t currentDraw = 0;
for ( auto graphic : graphics ) {
@ -826,15 +822,14 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
if ( graphic->descriptor.renderMode != this->getName() ) continue;
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass);
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, ::fmt::format("graphic[{}]", currentDraw) );
graphic->record( commandBuffer, descriptor, eye, currentDraw++, frame );
}
if ( eye + 1 < metadata.eyes ) {
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "nextSubpass" );
vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE); ++currentSubpass;
graphic->record( commandBuffer, descriptor, 0, currentDraw++, frame );
}
}
// skip deferred pass if RT is enabled, we still process geometry for a depth buffer
if ( DEFERRED_MODE == "fragment" ) for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
if ( DEFERRED_MODE == "fragment" ) {
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "nextSubpass" );
vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE); ++currentSubpass;
size_t currentPass = 0;
size_t currentDraw = 0;
{
@ -844,11 +839,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
descriptor.subpass = currentSubpass;
descriptor.bind.point = VK_PIPELINE_BIND_POINT_GRAPHICS;
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "deferred" );
blitter.record(commandBuffer, descriptor, eye, currentDraw++, frame);
}
if ( eye + 1 < metadata.eyes ) {
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "nextSubpass" );
vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE); ++currentSubpass;
blitter.record(commandBuffer, descriptor, 0, currentDraw++, frame);
}
}
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::END, "renderPass[end]" );

View File

@ -18,15 +18,6 @@ const uf::stl::string ext::vulkan::RenderTargetRenderMode::getType() const {
ext::vulkan::GraphicDescriptor ext::vulkan::RenderTargetRenderMode::bindGraphicDescriptor( const ext::vulkan::GraphicDescriptor& reference, size_t pass ) {
ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass);
/*
descriptor.parse(metadata.json["descriptor"]);
// invalidate
if ( metadata.target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != metadata.target ) {
descriptor.invalidated = true;
} else {
descriptor.renderMode = this->getName();
}
*/
if ( 0 <= pass && pass < metadata.subpasses && metadata.type == uf::renderer::settings::pipelines::names::vxgi ) {
descriptor.cullMode = VK_CULL_MODE_NONE;
@ -56,7 +47,6 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
}
if ( metadata.type == "depth" || metadata.type == uf::renderer::settings::pipelines::names::vxgi ) {
renderTarget.views = metadata.subpasses;
struct {
size_t depth;
} attachments = {};
@ -82,152 +72,33 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
);
}
} else if ( metadata.type == settings::pipelines::names::rt ) {
#if 1
struct {
size_t depth, color, bright, motion, scratch, output;
} attachments = {};
bool blend = true;
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::formats::depth,
/*.layout = */VK_IMAGE_LAYOUT_GENERAL,
/*.usage = */VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
/*.blend = */false,
/*.samples = */1,
});
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.bright = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.scratch = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.motion = renderTarget.attach(RenderTarget::Attachment::Descriptor{
// /*.format = */VK_FORMAT_R32G32B32A32_SFLOAT,
/*.format = */VK_FORMAT_R16G16_SFLOAT,
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */false,
/*.samples = */1,
});
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{},
{},
{},
attachments.depth,
0,
true
);
metadata.attachments["depth"] = attachments.depth;
metadata.attachments["color"] = attachments.color;
metadata.attachments["bright"] = attachments.bright;
metadata.attachments["motion"] = attachments.motion;
metadata.attachments["scratch"] = attachments.scratch;
metadata.attachments["output"] = attachments.color;
#endif
UF_EXCEPTION("unimplemented");
} else if ( metadata.type == "full" ) {
#if 0
UF_EXCEPTION("unimplemented");
} else {
struct {
size_t id, position, normal, depth, color;
size_t color, depth;
} attachments = {};
// input g-buffers
attachments.id = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R32G32_UINT,
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.position = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16B16A16_SFLOAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.normal = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16B16A16_SFLOAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.blend = */true,
/*.samples = */msaa,
});
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::formats::depth,
/*.layout = */VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
// output buffers
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
/*.format = */ ext::vulkan::settings::formats::depth,
/*.layout = */ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
metadata.attachments["id"] = attachments.id;
metadata.attachments["position"] = attachments.position;
metadata.attachments["normal"] = attachments.normal;
metadata.attachments["depth"] = attachments.depth;
metadata.attachments["color"] = attachments.color;
metadata.attachments["output"] = attachments.color;
metadata.attachments["depth"] = attachments.depth;
// First pass: fill the G-Buffer
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
renderTarget.addPass(
/*.*/ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
/*.colors =*/ { attachments.id, attachments.uv, attachments.normal },
/*.inputs =*/ {},
/*.resolve =*/{},
/*.depth = */ attachments.depth,
/*.layer = */eye,
/*.autoBuildPipeline =*/ true
);
}
#endif
} else {
for ( size_t currentPass = 0; currentPass < metadata.subpasses; ++currentPass ) {
struct {
size_t color, depth;
} attachments = {};
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */true,
/*.samples = */msaa,
});
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::depth,
/*.layout = */ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.color },
@ -237,9 +108,6 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
0,
true
);
metadata.attachments["color"] = attachments.color;
metadata.attachments["depth"] = attachments.depth;
}
}
@ -413,39 +281,28 @@ void ext::vulkan::RenderTargetRenderMode::destroy() {
}
void ext::vulkan::RenderTargetRenderMode::render() {
// if ( this->executed ) return;
if ( this->commands.container().empty() ) return;
//lockMutex( this->mostRecentCommandPoolId );
auto& commands = getCommands( this->mostRecentCommandPoolId );
VK_COMMAND_BUFFER_CALLBACK( EXECUTE_BEGIN, VkCommandBuffer{}, 0, {} );
// Submit commands
// Use a fence to ensure that command buffer has finished executing before using it again
/*
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT ));
VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[states::currentBuffer] ));
*/
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = NULL; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitSemaphores = NULL; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.waitSemaphoreCount = 0; // One wait semaphore
submitInfo.pSignalSemaphores = NULL; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.signalSemaphoreCount = 0; // One signal semaphore
submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission)
submitInfo.pWaitDstStageMask = NULL;
submitInfo.pWaitSemaphores = NULL;
submitInfo.waitSemaphoreCount = 0;
submitInfo.pSignalSemaphores = NULL;
submitInfo.signalSemaphoreCount = 0;
submitInfo.pCommandBuffers = &commands[states::currentBuffer];
submitInfo.commandBufferCount = 1;
// VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer]));
VkQueue queue = device->getQueue( QueueEnum::GRAPHICS );
VkResult res = vkQueueSubmit( queue, 1, &submitInfo, VK_NULL_HANDLE/*fences[states::currentBuffer]*/);
VK_CHECK_QUEUE_CHECKPOINT( queue, res );
VK_COMMAND_BUFFER_CALLBACK( EXECUTE_END, VkCommandBuffer{}, 0, {} );
this->executed = true;
//unlockMutex( this->mostRecentCommandPoolId );
}
void ext::vulkan::RenderTargetRenderMode::pipelineBarrier( VkCommandBuffer commandBuffer, uint8_t state ) {
ext::vulkan::RenderMode::pipelineBarrier( commandBuffer, state );
@ -463,17 +320,15 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
uf::stl::vector<VkClearValue> clearValues;
for ( size_t j = 0; j < renderTarget.views; ++j ) {
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 };
}
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 };
}
}
}
@ -514,29 +369,6 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v
size_t subpasses = renderTarget.passes.size();
size_t currentPass = 0;
//
// this->pipelineBarrier( commands[frame], 1 );
// VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
// VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
// VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
// VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
#if 0
for ( auto& attachment : renderTarget.attachments ) {
// transition attachments to general attachments for imageStore
VkImageSubresourceRange subresourceRange;
subresourceRange.baseMipLevel = 0;
subresourceRange.baseArrayLayer = 0;
subresourceRange.levelCount = attachment.descriptor.mips;
subresourceRange.layerCount = renderTarget.views;
subresourceRange.aspectMask = attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "setImageLayout" );
uf::renderer::Texture::setImageLayout( commandBuffer, attachment.image, VK_IMAGE_LAYOUT_UNDEFINED, attachment.descriptor.layout, subresourceRange );
}
#endif
// pre-renderpass commands
VK_COMMAND_BUFFER_CALLBACK( CALLBACK_BEGIN, commandBuffer, frame, {
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "callback[begin]" );
@ -605,8 +437,6 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v
VK_COMMAND_BUFFER_CALLBACK( CALLBACK_END, commandBuffer, frame, {
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "callback[end]" );
} );
// this->pipelineBarrier( commands[frame], 1 );
}
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::END, "end" );
VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer));

View File

@ -85,9 +85,8 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
subresourceRange.baseMipLevel = 0;
subresourceRange.levelCount = 1;
subresourceRange.baseArrayLayer = 0;
subresourceRange.layerCount = 1;
subresourceRange.aspectMask = isDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
subresourceRange.layerCount = 1;
subresourceRange.layerCount = this->views;
auto commandBuffer = device->fetchCommandBuffer(uf::renderer::QueueEnum::GRAPHICS);
for ( size_t i = 0; i < ext::vulkan::swapchain.buffers; ++i ) {
@ -167,6 +166,12 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
VK_CHECK_RESULT(vkCreateImageView(*device, &imageView, nullptr, &attachment->view));
VK_REGISTER_HANDLE( attachment->view );
if ( imageView.subresourceRange.levelCount > 1 ) {
imageView.subresourceRange.levelCount = 1;
VK_CHECK_RESULT(vkCreateImageView(*device, &imageView, nullptr, &attachment->framebufferView));
VK_REGISTER_HANDLE( attachment->framebufferView );
}
size_t viewIndex = 0;
for ( size_t layer = 0; layer < this->views; ++layer ) {
imageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
@ -237,21 +242,19 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
if ( !renderPass ) {
uf::stl::vector<VkAttachmentDescription> attachments; attachments.reserve( this->attachments.size() );
for ( size_t i = 0; i < this->views; ++i ) {
for ( auto& attachment : this->attachments ) {
VkAttachmentDescription description;
description.format = attachment.descriptor.format;
description.samples = ext::vulkan::sampleCount( attachment.descriptor.samples );
description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
description.storeOp = attachment.descriptor.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // isSwapchain ? VK_IMAGE_LAYOUT_UNDEFINED : attachment.descriptor.layout; // VK_IMAGE_LAYOUT_UNDEFINED;
description.finalLayout = ext::vulkan::Texture::remapRenderpassLayout( attachment.descriptor.layout );
description.flags = 0;
for ( auto& attachment : this->attachments ) {
VkAttachmentDescription description;
description.format = attachment.descriptor.format;
description.samples = ext::vulkan::sampleCount( attachment.descriptor.samples );
description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
description.storeOp = attachment.descriptor.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // isSwapchain ? VK_IMAGE_LAYOUT_UNDEFINED : attachment.descriptor.layout; // VK_IMAGE_LAYOUT_UNDEFINED;
description.finalLayout = ext::vulkan::Texture::remapRenderpassLayout( attachment.descriptor.layout );
description.flags = 0;
attachments.emplace_back(description);
}
attachments.emplace_back(description);
}
// ensure that the subpasses are already described
@ -259,12 +262,14 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
assert( passes.size() > 0 );
// expand attachment indices
/*
for ( auto& pass : passes ) {
for ( auto& input : pass.inputs ) input.attachment += pass.layer * this->attachments.size();
for ( auto& color : pass.colors ) color.attachment += pass.layer * this->attachments.size();
for ( auto& resolve : pass.resolves ) resolve.attachment += pass.layer * this->attachments.size();
pass.depth.attachment += pass.layer * this->attachments.size();
}
*/
uf::stl::vector<VkSubpassDescription> descriptions;
uf::stl::vector<VkSubpassDependency> dependencies;
@ -380,6 +385,26 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
renderPassInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
renderPassInfo.pDependencies = &dependencies[0];
uint32_t viewMask = (1 << this->views) - 1;
uf::stl::vector<uint32_t> viewMasks(descriptions.size(), viewMask);
uf::stl::vector<uint32_t> correlationMasks = { viewMask };
VkRenderPassMultiviewCreateInfo multiviewInfo = {};
multiviewInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
if ( this->views > 1 ) {
multiviewInfo.pNext = nullptr;
multiviewInfo.subpassCount = static_cast<uint32_t>(viewMasks.size());
multiviewInfo.pViewMasks = viewMasks.data();
multiviewInfo.dependencyCount = 0;
multiviewInfo.pViewOffsets = nullptr;
multiviewInfo.correlationMaskCount = 1;
multiviewInfo.pCorrelationMasks = correlationMasks.data();
renderPassInfo.pNext = &multiviewInfo;
}
VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass));
VK_REGISTER_HANDLE( renderPass );
}
@ -394,13 +419,13 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
for ( size_t frame = 0; frame < framebuffers.size(); ++frame ) {
uf::stl::vector<VkImageView> attachmentViews;
for ( auto view = 0; view < this->views; ++view ) {
for ( auto& attachment : this->attachments ) {
if ( attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) {
attachmentViews.emplace_back(attachment.views[frame]);
} else {
attachmentViews.emplace_back(attachment.views[view * attachment.descriptor.mips]);
}
for ( auto& attachment : this->attachments ) {
if ( attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) {
attachmentViews.emplace_back(attachment.views[frame]);
} else if ( attachment.framebufferView != VK_NULL_HANDLE ) {
attachmentViews.emplace_back(attachment.framebufferView);
} else {
attachmentViews.emplace_back(attachment.view);
}
}
@ -434,6 +459,11 @@ void ext::vulkan::RenderTarget::destroy() {
for ( auto& attachment : attachments ) {
if ( attachment.descriptor.aliased ) continue;
if ( attachment.framebufferView ) {
vkDestroyImageView(*device, attachment.framebufferView, nullptr);
VK_UNREGISTER_HANDLE( attachment.framebufferView );
}
if ( attachment.view ) {
if ( attachment.view != attachment.views.front() ) {
vkDestroyImageView(*device, attachment.view, nullptr);

View File

@ -495,7 +495,7 @@ void ext::vulkan::initialize( bool soft ) {
void ext::vulkan::tick() {
// ext::vulkan::mutex.lock();
if ( ext::vulkan::states::resized ) {
// synchronize(0b11);
synchronize(0b11);
ext::vulkan::states::rebuild = true;
::skip = true;
}