Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 119-graphicspipeline-refactoring
  • 129-projekte-und-assets-auslagern
  • 132-denoising-module
  • 143-ar-vr-support-via-openxr
  • 43-multi-threading
  • 91-compute-first-network
  • 95-arm64-raspberry-pi-4-support
  • develop
  • master
  • optimizations
  • 0.1.0
  • 0.2.0
12 results

Target

Select target project
  • vulkan2021/vkcv-framework
1 result
Select Git revision
  • 119-graphicspipeline-refactoring
  • 129-projekte-und-assets-auslagern
  • 132-denoising-module
  • 143-ar-vr-support-via-openxr
  • 43-multi-threading
  • 91-compute-first-network
  • 95-arm64-raspberry-pi-4-support
  • develop
  • master
  • optimizations
  • 0.1.0
  • 0.2.0
12 results
Show changes
Showing
with 360 additions and 100 deletions
......@@ -38,6 +38,9 @@ include(config/FidelityFX_FSR2.cmake)
# Check and load NVIDIAImageScaling
include(config/NVIDIAImageScaling.cmake)
# Add compile definitions depending on the build context of the module
add_compile_definitions(${vkcv_upscaling_definitions})
# adding source files to the project
add_library(vkcv_upscaling ${vkcv_build_attribute} ${vkcv_upscaling_sources})
......
use_git_submodule("${vkcv_upscaling_lib_path}/FidelityFX-FSR2" ffx_fsr2_status)
set(vkcv_upscaling_fsr2_override ON)
if (${ffx_fsr2_status})
set(FFX_FSR2_API_DX12 OFF CACHE INTERNAL "")
set(FFX_FSR2_API_VK ON CACHE INTERNAL "")
if (WIN32)
set(vkcv_upscaling_fsr2_override OFF)
else()
find_program(wine_program "wine")
add_subdirectory(${vkcv_upscaling_lib}/FidelityFX-FSR2/src/ffx-fsr2-api)
list(APPEND vkcv_upscaling_libraries ${FFX_FSR2_API} ${FFX_FSR2_API_VK})
if (EXISTS ${wine_program})
set(vkcv_upscaling_fsr2_override OFF)
endif()
endif()
if (vkcv_upscaling_fsr2_override)
list(APPEND vkcv_upscaling_definitions VKCV_OVERRIDE_FSR2_WITH_FSR1=1)
else()
use_git_submodule("${vkcv_upscaling_lib_path}/FidelityFX-FSR2" ffx_fsr2_status)
list(APPEND vkcv_upscaling_includes ${vkcv_upscaling_lib}/FidelityFX-FSR2/src/ffx-fsr2-api)
list(APPEND vkcv_upscaling_includes ${vkcv_upscaling_lib}/FidelityFX-FSR2/src/ffx-fsr2-api/vk)
endif ()
if (${ffx_fsr2_status})
set(FFX_FSR2_API_DX12 OFF CACHE INTERNAL "")
set(FFX_FSR2_API_VK ON CACHE INTERNAL "")
add_subdirectory(${vkcv_upscaling_lib}/FidelityFX-FSR2/src/ffx-fsr2-api)
list(APPEND vkcv_upscaling_libraries ${FFX_FSR2_API} ${FFX_FSR2_API_VK})
list(APPEND vkcv_upscaling_includes ${vkcv_upscaling_lib}/FidelityFX-FSR2/src/ffx-fsr2-api)
list(APPEND vkcv_upscaling_includes ${vkcv_upscaling_lib}/FidelityFX-FSR2/src/ffx-fsr2-api/vk)
endif ()
endif()
\ No newline at end of file
......@@ -2,10 +2,15 @@
#include "Upscaling.hpp"
#include <memory>
#include <vector>
#ifdef VKCV_OVERRIDE_FSR2_WITH_FSR1
#include "FSRUpscaling.hpp"
#else
struct FfxFsr2ContextDescription;
struct FfxFsr2Context;
#endif
namespace vkcv::upscaling {
......@@ -78,6 +83,9 @@ namespace vkcv::upscaling {
*/
class FSR2Upscaling : public Upscaling {
private:
#ifdef VKCV_OVERRIDE_FSR2_WITH_FSR1
std::unique_ptr<FSRUpscaling> m_fsr1;
#else
std::vector<char> m_scratchBuffer;
std::unique_ptr<FfxFsr2ContextDescription> m_description;
......@@ -118,6 +126,7 @@ namespace vkcv::upscaling {
uint32_t renderHeight);
void destroyFSR2Context();
#endif
public:
/**
......
Subproject commit 0ce4ff5c5a0210273be7e3085bb4b15d0590431c
Subproject commit 59950a85247baa4e099537324912a1f0e3a7b5d5
Subproject commit 7a468267104585ce5cd683aebd8e4cb74f826807
Subproject commit 35e13ba316c98eeecf16f37eae70ce88019911f6
......@@ -3,10 +3,18 @@
#include <cmath>
#ifndef VKCV_OVERRIDE_FSR2_WITH_FSR1
#ifndef _MSVC_LANG
#define FFX_GCC
#endif
#include <ffx_fsr2.h>
#include <ffx_fsr2_vk.h>
#ifdef FFX_GCC
#undef FFX_GCC
#endif
#endif
namespace vkcv::upscaling {
......@@ -57,6 +65,7 @@ namespace vkcv::upscaling {
}
}
#ifndef VKCV_OVERRIDE_FSR2_WITH_FSR1
void FSR2Upscaling::createFSR2Context(uint32_t displayWidth,
uint32_t displayHeight,
uint32_t renderWidth,
......@@ -143,20 +152,29 @@ namespace vkcv::upscaling {
m_scratchBuffer.clear();
m_description->callbacks.scratchBuffer = nullptr;
}
#else
FSR2Upscaling::FSR2Upscaling(vkcv::Core &core) :
Upscaling(core), m_fsr1(new FSRUpscaling(m_core)) {}
FSR2Upscaling::~FSR2Upscaling() {}
#endif
void FSR2Upscaling::update(float deltaTime, bool reset) {
#ifndef VKCV_OVERRIDE_FSR2_WITH_FSR1
if (reset) {
m_frameIndex = 0;
}
m_frameDeltaTime = deltaTime;
m_reset = reset;
#endif
}
void FSR2Upscaling::calcJitterOffset(uint32_t renderWidth,
uint32_t renderHeight,
float &jitterOffsetX,
float &jitterOffsetY) const {
#ifndef VKCV_OVERRIDE_FSR2_WITH_FSR1
const int32_t phaseCount = ffxFsr2GetJitterPhaseCount(
static_cast<int32_t>(renderWidth),
static_cast<int32_t>(renderHeight)
......@@ -173,23 +191,34 @@ namespace vkcv::upscaling {
jitterOffsetX *= +2.0f / renderWidth;
jitterOffsetY *= -2.0f / renderHeight;
#else
jitterOffsetX = 0.0f;
jitterOffsetY = 0.0f;
#endif
}
void FSR2Upscaling::bindDepthBuffer(const ImageHandle &depthInput) {
#ifndef VKCV_OVERRIDE_FSR2_WITH_FSR1
m_depth = depthInput;
#endif
}
void FSR2Upscaling::bindVelocityBuffer(const ImageHandle &velocityInput) {
#ifndef VKCV_OVERRIDE_FSR2_WITH_FSR1
m_velocity = velocityInput;
#endif
}
void FSR2Upscaling::recordUpscaling(const CommandStreamHandle &cmdStream,
const ImageHandle &colorInput,
const ImageHandle &output) {
#ifndef VKCV_OVERRIDE_FSR2_WITH_FSR1
m_core.recordBeginDebugLabel(cmdStream, "vkcv::upscaling::FSR2Upscaling", {
1.0f, 0.05f, 0.05f, 1.0f
});
m_core.prepareImageForSampling(cmdStream, output);
FfxFsr2DispatchDescription dispatch;
memset(&dispatch, 0, sizeof(dispatch));
......@@ -322,28 +351,49 @@ namespace vkcv::upscaling {
m_core.updateImageLayoutManual(output, vk::ImageLayout::eGeneral);
m_core.recordEndDebugLabel(cmdStream);
#else
m_fsr1->recordUpscaling(cmdStream, colorInput, output);
#endif
}
void FSR2Upscaling::setCamera(float near, float far, float fov) {
#ifndef VKCV_OVERRIDE_FSR2_WITH_FSR1
m_near = near;
m_far = far;
m_fov = fov;
#endif
}
bool FSR2Upscaling::isHdrEnabled() const {
#ifdef VKCV_OVERRIDE_FSR2_WITH_FSR1
return m_fsr1->isHdrEnabled();
#else
return m_hdr;
#endif
}
void FSR2Upscaling::setHdrEnabled(bool enabled) {
#ifdef VKCV_OVERRIDE_FSR2_WITH_FSR1
m_fsr1->setHdrEnabled(true);
#else
m_hdr = enabled;
#endif
}
float FSR2Upscaling::getSharpness() const {
#ifdef VKCV_OVERRIDE_FSR2_WITH_FSR1
return m_fsr1->getSharpness();
#else
return m_sharpness;
#endif
}
void FSR2Upscaling::setSharpness(float sharpness) {
#ifdef VKCV_OVERRIDE_FSR2_WITH_FSR1
m_fsr1->setSharpness(sharpness);
#else
m_sharpness = (sharpness < 0.0f ? 0.0f : (sharpness > 1.0f ? 1.0f : sharpness));
#endif
}
}
\ No newline at end of file
......@@ -50,10 +50,9 @@ int main(int argc, const char** argv) {
// since we only use one descriptor set (namely, desc set 0), directly address it
// recreate copies of the bindings and the handles (to check whether they are properly reused instead of actually recreated)
const vkcv::DescriptorBindings& set0Bindings = firstMeshProgram.getReflectedDescriptors().at(0);
auto set0BindingsExplicitCopy = set0Bindings;
vkcv::DescriptorSetLayoutHandle setLayoutHandle = core.createDescriptorSetLayout(set0Bindings);
vkcv::DescriptorSetLayoutHandle setLayoutHandleCopy = core.createDescriptorSetLayout(set0BindingsExplicitCopy);
vkcv::DescriptorSetLayoutHandle setLayoutHandleCopy = core.createDescriptorSetLayout(set0Bindings);
vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(setLayoutHandle);
......@@ -88,7 +87,7 @@ int main(int argc, const char** argv) {
}
vkcv::SamplerHandle sampler = vkcv::samplerLinear(core);
vkcv::DescriptorWrites setWrites;
setWrites.writeSampledImage(0, texture.getHandle());
setWrites.writeSampler(1, sampler);
......@@ -145,5 +144,7 @@ int main(int argc, const char** argv) {
core.submitCommandStream(cmdStream);
});
core.getContext().getDevice().waitIdle();
return 0;
}
......@@ -384,11 +384,10 @@ void App::run() {
// upscaling
m_core.prepareImageForSampling(cmdStream, m_renderTargets.colorBuffer);
m_core.prepareImageForStorage(cmdStream, m_renderTargets.finalBuffer);
switch (upscalingMode) {
case 0:
m_core.prepareImageForStorage(cmdStream, m_renderTargets.finalBuffer);
fsr1.recordUpscaling(
cmdStream,
m_renderTargets.colorBuffer,
......@@ -399,8 +398,6 @@ void App::run() {
m_core.prepareImageForSampling(cmdStream, m_renderTargets.depthBuffer);
m_core.prepareImageForSampling(cmdStream, m_renderTargets.motionBuffer);
m_core.prepareImageForSampling(cmdStream, m_renderTargets.finalBuffer);
fsr2.recordUpscaling(
cmdStream,
m_renderTargets.colorBuffer,
......@@ -408,8 +405,6 @@ void App::run() {
);
break;
case 2:
m_core.prepareImageForStorage(cmdStream, m_renderTargets.finalBuffer);
nis.recordUpscaling(
cmdStream,
m_renderTargets.colorBuffer,
......@@ -417,8 +412,6 @@ void App::run() {
);
break;
case 3:
m_core.prepareImageForStorage(cmdStream, m_renderTargets.finalBuffer);
bilinear.recordUpscaling(
cmdStream,
m_renderTargets.colorBuffer,
......
......@@ -7,15 +7,63 @@
#include "vkcv/Core.hpp"
#include <vkcv/Logger.hpp>
#include <limits>
namespace vkcv {
bool BufferManager::init(Core &core) {
if (!HandleManager<BufferEntry, BufferHandle>::init(core)) {
return false;
}
const vma::Allocator &allocator = getCore().getContext().getAllocator();
const auto& memoryProperties = allocator.getMemoryProperties();
const auto& heaps = memoryProperties->memoryHeaps;
std::vector<vk::MemoryPropertyFlags> heapMemoryFlags;
heapMemoryFlags.resize(heaps.size());
for (const auto& type : memoryProperties->memoryTypes) {
if (type.heapIndex >= heaps.size()) {
continue;
}
heapMemoryFlags[type.heapIndex] |= type.propertyFlags;
}
vk::DeviceSize maxDeviceHeapSize = 0;
uint32_t deviceHeapIndex = 0;
for (uint32_t i = 0; i < heaps.size(); i++) {
if (!(heaps[i].flags & vk::MemoryHeapFlagBits::eDeviceLocal)) {
continue;
}
if (!(heapMemoryFlags[i] & vk::MemoryPropertyFlagBits::eDeviceLocal)) {
continue;
}
if (heaps[i].size < maxDeviceHeapSize) {
continue;
}
maxDeviceHeapSize = heaps[i].size;
deviceHeapIndex = i;
}
if (heapMemoryFlags[deviceHeapIndex] & vk::MemoryPropertyFlagBits::eHostVisible) {
m_resizableBar = true;
} else {
m_resizableBar = false;
}
m_stagingBuffer = createBuffer(TypeGuard(1), BufferType::STAGING,
BufferMemoryType::HOST_VISIBLE, 1024 * 1024, false);
m_stagingBuffer = createBuffer(
TypeGuard(1),
BufferType::STAGING,
BufferMemoryType::HOST_VISIBLE,
1024 * 1024,
false
);
return true;
}
......@@ -34,6 +82,10 @@ namespace vkcv {
const vma::Allocator &allocator = getCore().getContext().getAllocator();
if (buffer.m_handle) {
if (buffer.m_mapping) {
allocator.unmapMemory(buffer.m_allocation);
}
allocator.destroyBuffer(buffer.m_handle, buffer.m_allocation);
buffer.m_handle = nullptr;
......@@ -42,7 +94,9 @@ namespace vkcv {
}
BufferManager::BufferManager() noexcept :
HandleManager<BufferEntry, BufferHandle>(), m_stagingBuffer(BufferHandle()) {}
HandleManager<BufferEntry, BufferHandle>(),
m_resizableBar(false),
m_stagingBuffer(BufferHandle()) {}
BufferManager::~BufferManager() noexcept {
clear();
......@@ -65,15 +119,15 @@ namespace vkcv {
usageFlags = vk::BufferUsageFlagBits::eStorageBuffer;
break;
case BufferType::STAGING:
usageFlags =
vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst;
usageFlags = vk::BufferUsageFlagBits::eTransferSrc
| vk::BufferUsageFlagBits::eTransferDst;
break;
case BufferType::INDEX:
usageFlags = vk::BufferUsageFlagBits::eIndexBuffer;
break;
case BufferType::INDIRECT:
usageFlags =
vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndirectBuffer;
usageFlags = vk::BufferUsageFlagBits::eStorageBuffer
| vk::BufferUsageFlagBits::eIndirectBuffer;
break;
default:
vkcv_log(LogLevel::WARNING, "Unknown buffer type");
......@@ -90,20 +144,16 @@ namespace vkcv {
const vma::Allocator &allocator = getCore().getContext().getAllocator();
vk::MemoryPropertyFlags memoryTypeFlags;
vma::MemoryUsage memoryUsage;
bool mappable = false;
switch (memoryType) {
case BufferMemoryType::DEVICE_LOCAL:
memoryTypeFlags = vk::MemoryPropertyFlagBits::eDeviceLocal;
memoryUsage = vma::MemoryUsage::eGpuOnly;
memoryUsage = vma::MemoryUsage::eAutoPreferDevice;
mappable = false;
break;
case BufferMemoryType::HOST_VISIBLE:
memoryTypeFlags = vk::MemoryPropertyFlagBits::eHostVisible
| vk::MemoryPropertyFlagBits::eHostCoherent;
memoryUsage = vma::MemoryUsage::eCpuOnly;
memoryUsage = vma::MemoryUsage::eAutoPreferHost;
mappable = true;
break;
default:
......@@ -112,20 +162,57 @@ namespace vkcv {
mappable = false;
break;
}
if (type == BufferType::STAGING) {
memoryUsage = vma::MemoryUsage::eCpuToGpu;
vma::AllocationCreateFlags allocationCreateFlags;
if (mappable) {
if (type == vkcv::BufferType::STAGING) {
allocationCreateFlags = vma::AllocationCreateFlagBits::eHostAccessSequentialWrite;
} else {
allocationCreateFlags = vma::AllocationCreateFlagBits::eHostAccessRandom;
}
} else
if ((m_resizableBar) && (memoryType == BufferMemoryType::DEVICE_LOCAL)) {
allocationCreateFlags = vma::AllocationCreateFlagBits::eHostAccessAllowTransferInstead
| vma::AllocationCreateFlagBits::eHostAccessSequentialWrite;
}
auto bufferAllocation = allocator.createBuffer(
vk::BufferCreateInfo(createFlags, size, usageFlags),
vma::AllocationCreateInfo(vma::AllocationCreateFlags(), memoryUsage, memoryTypeFlags,
memoryTypeFlags, 0, vma::Pool(), nullptr));
vma::AllocationCreateInfo(
allocationCreateFlags,
memoryUsage,
vk::MemoryPropertyFlags(),
vk::MemoryPropertyFlags(),
0,
vma::Pool(),
nullptr
)
);
vk::Buffer buffer = bufferAllocation.first;
vma::Allocation allocation = bufferAllocation.second;
const vk::MemoryPropertyFlags finalMemoryFlags = allocator.getAllocationMemoryProperties(
allocation
);
if (vk::MemoryPropertyFlagBits::eHostVisible & finalMemoryFlags) {
mappable = true;
}
return add({ typeGuard, type, memoryType, size, buffer, allocation, mappable });
return add({
typeGuard,
type,
memoryType,
size,
buffer,
allocation,
readable,
mappable,
nullptr,
0
});
}
/**
......@@ -287,7 +374,7 @@ namespace vkcv {
auto &buffer = (*this) [handle];
if (size == 0) {
size = SIZE_MAX;
size = std::numeric_limits<size_t>::max();
}
const vma::Allocator &allocator = getCore().getContext().getAllocator();
......@@ -326,7 +413,7 @@ namespace vkcv {
auto &buffer = (*this) [handle];
if (size == 0) {
size = SIZE_MAX;
size = std::numeric_limits<size_t>::max();
}
const vma::Allocator &allocator = getCore().getContext().getAllocator();
......@@ -364,24 +451,68 @@ namespace vkcv {
auto &buffer = (*this) [handle];
if (size == 0) {
size = SIZE_MAX;
size = std::numeric_limits<size_t>::max();
}
const vma::Allocator &allocator = getCore().getContext().getAllocator();
if (offset > buffer.m_size) {
return nullptr;
}
return reinterpret_cast<char*>(allocator.mapMemory(buffer.m_allocation)) + offset;
if (buffer.m_mapping) {
++buffer.m_mapCounter;
vkcv_log(LogLevel::WARNING,
"Mapping a buffer multiple times (%lu) is not recommended",
buffer.m_mapCounter);
return buffer.m_mapping + offset;
}
if (buffer.m_mappable) {
const vma::Allocator &allocator = getCore().getContext().getAllocator();
buffer.m_mapping = reinterpret_cast<char*>(allocator.mapMemory(buffer.m_allocation));
} else {
buffer.m_mapping = m_allocator.allocate(buffer.m_size);
if (buffer.m_readable) {
readBuffer(handle, buffer.m_mapping, buffer.m_size, 0);
}
}
buffer.m_mapCounter = 1;
return buffer.m_mapping + offset;
}
void BufferManager::unmapBuffer(const BufferHandle &handle) {
auto &buffer = (*this) [handle];
const vma::Allocator &allocator = getCore().getContext().getAllocator();
allocator.unmapMemory(buffer.m_allocation);
if (buffer.m_mapCounter > 1) {
--buffer.m_mapCounter;
return;
}
if (buffer.m_mapCounter == 0) {
vkcv_log(LogLevel::WARNING,
"It seems like the buffer is not mapped to memory");
}
if (!buffer.m_mapping) {
vkcv_log(LogLevel::ERROR,
"Buffer is not mapped to memory");
}
if (buffer.m_mappable) {
const vma::Allocator &allocator = getCore().getContext().getAllocator();
allocator.unmapMemory(buffer.m_allocation);
} else {
fillBuffer(handle, buffer.m_mapping, buffer.m_size, 0);
m_allocator.deallocate(buffer.m_mapping, buffer.m_size);
}
buffer.m_mapping = nullptr;
buffer.m_mapCounter = 0;
}
void BufferManager ::recordBufferMemoryBarrier(const BufferHandle &handle,
......
......@@ -5,7 +5,9 @@
* @brief Manager to handle buffer operations.
*/
#include <memory>
#include <vector>
#include <vk_mem_alloc.hpp>
#include <vulkan/vulkan.hpp>
......@@ -26,7 +28,10 @@ namespace vkcv {
vk::Buffer m_handle;
vma::Allocation m_allocation;
bool m_readable;
bool m_mappable;
char *m_mapping;
size_t m_mapCounter;
};
/**
......@@ -37,6 +42,9 @@ namespace vkcv {
friend class Core;
private:
std::allocator<char> m_allocator;
bool m_resizableBar;
BufferHandle m_stagingBuffer;
bool init(Core &core) override;
......
......@@ -3,6 +3,8 @@
#include "vkcv/Logger.hpp"
#include <limits>
namespace vkcv {
uint64_t CommandStreamManager::getIdFrom(const CommandStreamHandle &handle) const {
......@@ -86,7 +88,12 @@ namespace vkcv {
signalSemaphores);
stream.queue.submit(queueSubmitInfo, waitFence);
assert(device.waitForFences(waitFence, true, UINT64_MAX) == vk::Result::eSuccess);
const auto result = device.waitForFences(waitFence, true, std::numeric_limits<uint64_t>::max());
if (result == vk::Result::eTimeout) {
device.waitIdle();
}
device.destroyFence(waitFence);
stream.queue = nullptr;
......
......@@ -4,6 +4,7 @@
#include "vkcv/Window.hpp"
namespace vkcv {
Context::Context(Context &&other) noexcept :
m_Instance(other.m_Instance), m_PhysicalDevice(other.m_PhysicalDevice),
m_Device(other.m_Device), m_FeatureManager(std::move(other.m_FeatureManager)),
......@@ -147,7 +148,7 @@ namespace vkcv {
std::vector<std::string> getRequiredExtensions() {
std::vector<std::string> extensions = Window::getExtensions();
#ifndef NDEBUG
#ifdef VULKAN_DEBUG_LABELS
extensions.emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
#endif
......@@ -346,7 +347,7 @@ namespace vkcv {
}
// if in debug mode, check if validation layers are supported. Enable them if supported
#ifndef NDEBUG
#ifdef VULKAN_VALIDATION_LAYERS
std::vector<const char*> validationLayers = { "VK_LAYER_KHRONOS_validation" };
if (!checkSupport(supportedLayers, validationLayers)) {
......@@ -388,7 +389,7 @@ namespace vkcv {
vk::InstanceCreateFlags(), &applicationInfo, 0, nullptr,
static_cast<uint32_t>(requiredExtensions.size()), requiredExtensions.data());
#ifndef NDEBUG
#ifdef VULKAN_VALIDATION_LAYERS
instanceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
instanceCreateInfo.ppEnabledLayerNames = validationLayers.data();
#endif
......@@ -478,7 +479,7 @@ namespace vkcv {
vk::DeviceCreateFlags(), qCreateInfos.size(), qCreateInfos.data(), 0, nullptr,
extensions.size(), extensions.data(), nullptr, &(featureManager.getFeatures()));
#ifndef NDEBUG
#ifdef VULKAN_VALIDATION_LAYERS
deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
deviceCreateInfo.ppEnabledLayerNames = validationLayers.data();
#endif
......
#include "vkcv/Handles.hpp"
#include <iostream>
#include <limits>
namespace vkcv {
Handle::Handle() : m_id(UINT64_MAX), m_rc(nullptr), m_destroy(nullptr) {}
Handle::Handle() : m_id(std::numeric_limits<uint64_t>::max()), m_rc(nullptr), m_destroy(nullptr) {}
Handle::Handle(uint64_t id, const HandleDestroyFunction &destroy) :
m_id(id), m_rc(new uint64_t(1)), m_destroy(destroy) {}
......@@ -29,6 +30,7 @@ namespace vkcv {
Handle::Handle(Handle &&other) noexcept :
m_id(other.m_id), m_rc(other.m_rc), m_destroy(other.m_destroy) {
other.m_rc = nullptr;
other.m_destroy = nullptr;
}
Handle &Handle::operator=(const Handle &other) {
......@@ -53,6 +55,7 @@ namespace vkcv {
m_destroy = other.m_destroy;
other.m_rc = nullptr;
other.m_destroy = nullptr;
return *this;
}
......@@ -66,11 +69,11 @@ namespace vkcv {
}
Handle::operator bool() const {
return (m_id < UINT64_MAX);
return (m_id < std::numeric_limits<uint64_t>::max());
}
bool Handle::operator!() const {
return (m_id == UINT64_MAX);
return (m_id == std::numeric_limits<uint64_t>::max());
}
std::ostream &operator<<(std::ostream &out, const Handle &handle) {
......@@ -83,11 +86,11 @@ namespace vkcv {
}
bool ImageHandle::isSwapchainImage() const {
return (getId() == UINT64_MAX - 1);
return (getId() == std::numeric_limits<uint64_t>::max() - 1);
}
ImageHandle ImageHandle::createSwapchainImageHandle(const HandleDestroyFunction &destroy) {
return ImageHandle(uint64_t(UINT64_MAX - 1), destroy);
return ImageHandle(uint64_t(std::numeric_limits<uint64_t>::max() - 1), destroy);
}
} // namespace vkcv
......@@ -340,6 +340,9 @@ namespace vkcv {
arrayViews.push_back(device.createImageView(imageViewCreateInfo));
}
std::vector<vk::ImageLayout> layers;
layers.resize(arrayLayers, vk::ImageLayout::eUndefined);
return add({
image,
allocation,
......@@ -349,8 +352,7 @@ namespace vkcv {
config.getHeight(),
config.getDepth(),
format,
arrayLayers,
vk::ImageLayout::eUndefined,
layers,
config.isSupportingStorage()
});
}
......@@ -417,20 +419,22 @@ namespace vkcv {
mipLevelOffset,
mipLevelCount,
0,
image.m_layers
static_cast<uint32_t>(image.m_layers.size())
);
// TODO: precise AccessFlagBits, will require a lot of context
return vk::ImageMemoryBarrier(
vk::ImageMemoryBarrier barrier (
vk::AccessFlagBits::eMemoryWrite,
vk::AccessFlagBits::eMemoryRead,
image.m_layout,
image.m_layers[0],
newLayout,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
image.m_handle,
imageSubresourceRange
);
return barrier;
}
void ImageManager::switchImageLayoutImmediate(const ImageHandle &handle,
......@@ -445,14 +449,23 @@ namespace vkcv {
stream,
[transitionBarrier](const vk::CommandBuffer &commandBuffer) {
// TODO: precise PipelineStageFlagBits, will require a lot of context
commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eBottomOfPipe, {}, nullptr,
nullptr, transitionBarrier);
commandBuffer.pipelineBarrier(
vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eBottomOfPipe,
{},
nullptr,
nullptr,
transitionBarrier
);
},
nullptr);
nullptr
);
core.submitCommandStream(stream, false);
image.m_layout = newLayout;
for (auto& layer : image.m_layers) {
layer = newLayout;
}
}
void ImageManager::recordImageLayoutTransition(const ImageHandle &handle,
......@@ -460,25 +473,45 @@ namespace vkcv {
vk::ImageLayout newLayout,
vk::CommandBuffer cmdBuffer) {
auto &image = (*this) [handle];
const auto transitionBarrier =
createImageLayoutTransitionBarrier(image, mipLevelCount, mipLevelOffset, newLayout);
const auto transitionBarrier = createImageLayoutTransitionBarrier(
image,
mipLevelCount,
mipLevelOffset,
newLayout
);
cmdBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eAllCommands, {}, nullptr, nullptr,
transitionBarrier);
cmdBuffer.pipelineBarrier(
vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eAllCommands,
{},
nullptr,
nullptr,
transitionBarrier
);
image.m_layout = newLayout;
for (auto& layer : image.m_layers) {
layer = newLayout;
}
}
void ImageManager::recordImageMemoryBarrier(const ImageHandle &handle,
vk::CommandBuffer cmdBuffer) {
auto &image = (*this) [handle];
const auto transitionBarrier =
createImageLayoutTransitionBarrier(image, 0, 0, image.m_layout);
const auto transitionBarrier = createImageLayoutTransitionBarrier(
image,
0,
0,
image.m_layers[0]
);
cmdBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eAllCommands, {}, nullptr, nullptr,
transitionBarrier);
cmdBuffer.pipelineBarrier(
vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eAllCommands,
{},
nullptr,
nullptr,
transitionBarrier
);
}
constexpr uint32_t getBytesPerPixel(vk::Format format) {
......@@ -512,18 +545,20 @@ namespace vkcv {
}
auto &image = (*this) [handle];
const uint32_t baseArrayLayer = std::min<uint32_t>(firstLayer, image.m_layers);
if (baseArrayLayer >= image.m_layers) {
const auto imageLayerCount = static_cast<uint32_t>(image.m_layers.size());
const uint32_t baseArrayLayer = std::min<uint32_t>(firstLayer, imageLayerCount);
if (baseArrayLayer >= image.m_layers.size()) {
return;
}
uint32_t arrayLayerCount;
if (layerCount > 0) {
arrayLayerCount = std::min<uint32_t>(layerCount, image.m_layers - baseArrayLayer);
arrayLayerCount = std::min<uint32_t>(layerCount, imageLayerCount - baseArrayLayer);
} else {
arrayLayerCount = image.m_layers - baseArrayLayer;
arrayLayerCount = imageLayerCount - baseArrayLayer;
}
switchImageLayoutImmediate(handle, vk::ImageLayout::eTransferDstOptimal);
......@@ -596,10 +631,13 @@ namespace vkcv {
auto &srcImage = (*this) [src];
auto &dstImage = (*this) [dst];
const auto srcLayerCount = static_cast<uint32_t>(srcImage.m_layers.size());
const auto dstLayerCount = static_cast<uint32_t>(dstImage.m_layers.size());
vk::ImageResolve region(
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, srcImage.m_layers),
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, srcLayerCount),
vk::Offset3D(0, 0, 0),
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, dstImage.m_layers),
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, dstLayerCount),
vk::Offset3D(0, 0, 0),
vk::Extent3D(dstImage.m_width, dstImage.m_height, dstImage.m_depth)
);
......@@ -609,9 +647,9 @@ namespace vkcv {
cmdBuffer.resolveImage(
srcImage.m_handle,
srcImage.m_layout,
srcImage.m_layers[0],
dstImage.m_handle,
dstImage.m_layout,
dstImage.m_layers[0],
region
);
}
......@@ -656,7 +694,7 @@ namespace vkcv {
uint32_t ImageManager::getImageArrayLayers(const ImageHandle &handle) const {
auto &image = (*this) [handle];
return image.m_layers;
return static_cast<uint32_t>(image.m_layers.size());
}
void ImageManager::setCurrentSwapchainImageIndex(int index) {
......@@ -686,17 +724,18 @@ namespace vkcv {
height,
1,
format,
1,
vk::ImageLayout::eUndefined,
{ vk::ImageLayout::eUndefined },
false
});
}
}
void ImageManager::updateImageLayoutManual(const vkcv::ImageHandle &handle,
const vk::ImageLayout layout) {
vk::ImageLayout layout) {
auto &image = (*this) [handle];
image.m_layout = layout;
for (auto& layer : image.m_layers) {
layer = layout;
}
}
} // namespace vkcv
\ No newline at end of file
......@@ -35,8 +35,7 @@ namespace vkcv {
uint32_t m_depth;
vk::Format m_format;
uint32_t m_layers;
vk::ImageLayout m_layout;
std::vector<vk::ImageLayout> m_layers;
bool m_storage;
};
......@@ -140,6 +139,6 @@ namespace vkcv {
// if manual vulkan work, e.g. ImGui integration, changes an image layout this function must
// be used to update the internal image state
void updateImageLayoutManual(const vkcv::ImageHandle &handle, const vk::ImageLayout layout);
void updateImageLayoutManual(const vkcv::ImageHandle &handle, vk::ImageLayout layout);
};
} // namespace vkcv
\ No newline at end of file