Commit for 2020.07.24.7z

This commit is contained in:
mrq 2020-07-24 00:00:00 -05:00
parent 958b1697f6
commit 01ccc7fab4
36 changed files with 709 additions and 508 deletions

View File

@ -126,7 +126,7 @@ void client::initialize() {
ext::vulkan::width = size.x;
ext::vulkan::height = size.y;
ext::vulkan::swapchain.rebuild = true;
ext::vulkan::rebuild = true;
return "true";
} );
} else if ( client::config["engine"]["hook"]["mode"] == "Both" || client::config["engine"]["hook"]["mode"] == "Optimal" ) {

View File

@ -14,8 +14,8 @@ namespace ext {
void* mapped = nullptr;
VkBufferUsageFlags usageFlags;
VkMemoryPropertyFlags memoryPropertyFlags;
VkMemoryAllocateInfo memAlloc;
VkMemoryRequirements memReqs;

View File

@ -23,7 +23,7 @@ namespace ext {
uint32_t indices = 0;
VkSampler sampler;
ext::vulkan::RenderTarget* framebuffer;
ext::vulkan::RenderTarget* renderTarget;
virtual void createCommandBuffer( VkCommandBuffer );
virtual bool autoAssignable() const;

View File

@ -23,7 +23,7 @@ namespace ext {
uint32_t indices = 0;
VkSampler sampler;
ext::vulkan::RenderTarget* framebuffer;
ext::vulkan::RenderTarget* renderTarget;
virtual void createCommandBuffer( VkCommandBuffer );
virtual bool autoAssignable() const;

View File

@ -0,0 +1,31 @@
#pragma once
#include <uf/ext/vulkan/device.h>
namespace ext {
namespace vulkan {
struct Graphic;
struct UF_API RenderMode {
uint32_t width = 0, height = 0;
std::string name = "";
Device* device = VK_NULL_HANDLE;
ext::vulkan::RenderTarget renderTarget;
std::vector<VkFence> fences;
std::vector<VkCommandBuffer> commands;
// virtual ~RenderMode();
// RAII
virtual std::string getType() const;
const std::string& getName() const;
virtual size_t subpasses() const;
virtual void initialize( Device& device );
virtual void createCommandBuffers();
virtual void createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics, const std::vector<std::string>& passes );
virtual void render();
virtual void destroy();
};
}
}

View File

@ -1,15 +1,11 @@
#pragma once
#include <uf/ext/vulkan/device.h>
#include <uf/ext/vulkan/rendermode.h>
namespace ext {
namespace vulkan {
struct Graphic;
struct UF_API RenderMode {
uint32_t width = 0, height = 0;
std::string name = "";
Device* device = VK_NULL_HANDLE;
struct UF_API BaseRenderMode : RenderMode {
// virtual ~RenderMode();
// RAII
virtual std::string getType() const;
@ -17,13 +13,9 @@ namespace ext {
virtual size_t subpasses() const;
virtual void initialize( Device& device );
virtual void createCommandBuffers();
virtual void createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics, const std::vector<std::string>& passes );
virtual void render();
virtual void destroy();
virtual VkRenderPass& getRenderPass();
virtual ext::vulkan::RenderTarget& getRenderTarget();
};
}
}

View File

@ -1,13 +1,11 @@
#pragma once
#include <uf/ext/vulkan/device.h>
#include <uf/ext/vulkan/rendertarget.h>
#include <uf/ext/vulkan/rendermode.h>
#include <uf/ext/vulkan/graphics/framebuffer.h>
namespace ext {
namespace vulkan {
struct UF_API DeferredRenderMode : public ext::vulkan::RenderMode {
ext::vulkan::RenderTarget renderTarget;
ext::vulkan::FramebufferGraphic blitter;
// RAII
@ -17,9 +15,6 @@ namespace ext {
virtual void createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics, const std::vector<std::string>& passes );
virtual void initialize( Device& device );
virtual void destroy();
virtual VkRenderPass& getRenderPass();
virtual ext::vulkan::RenderTarget& getRenderTarget();
};
}
}

View File

@ -1,18 +1,18 @@
#pragma once
#include <uf/ext/vulkan/device.h>
#include <uf/ext/vulkan/rendertarget.h>
#include <uf/ext/vulkan/rendermode.h>
#include <uf/ext/vulkan/graphics/framebuffer.h>
namespace ext {
namespace vulkan {
struct UF_API MultiviewRenderMode : public ext::vulkan::RenderMode {
struct {
ext::vulkan::RenderTarget left;
ext::vulkan::RenderTarget& left;
ext::vulkan::RenderTarget right;
} renderTargets;
ext::vulkan::FramebufferGraphic blitter;
MultiviewRenderMode();
// RAII
virtual std::string getType() const;
virtual size_t subpasses() const;
@ -20,9 +20,6 @@ namespace ext {
virtual void createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics, const std::vector<std::string>& passes );
virtual void initialize( Device& device );
virtual void destroy();
virtual VkRenderPass& getRenderPass();
virtual ext::vulkan::RenderTarget& getRenderTarget();
};
}
}

View File

@ -1,14 +1,13 @@
#pragma once
#include <uf/ext/vulkan/device.h>
#include <uf/ext/vulkan/rendertarget.h>
#include <uf/ext/vulkan/rendermode.h>
#include <uf/ext/vulkan/graphics/rendertarget.h>
namespace ext {
namespace vulkan {
struct UF_API RenderTargetRenderMode : public ext::vulkan::RenderMode {
ext::vulkan::RenderTarget renderTarget;
ext::vulkan::RenderTargetGraphic blitter;
VkFence fence;
VkCommandBuffer commandBuffer;
@ -20,9 +19,6 @@ namespace ext {
virtual void initialize( Device& device );
virtual void destroy();
virtual void render();
virtual VkRenderPass& getRenderPass();
virtual ext::vulkan::RenderTarget& getRenderTarget();
};
}
}

View File

@ -9,6 +9,8 @@ namespace ext {
VkFormat format;
VkImageLayout layout;
VkImageUsageFlags usage;
bool aliased = false;
VkImage image;
VkDeviceMemory mem;
VkImageView view;
@ -33,7 +35,7 @@ namespace ext {
void initialize( Device& device );
void destroy();
void addPass( VkPipelineStageFlags, VkAccessFlags, const std::vector<size_t>&, const std::vector<size_t>&, size_t );
size_t attach( VkFormat format, VkImageUsageFlags usage, Attachment* attachment = NULL );
size_t attach( VkFormat format, VkImageUsageFlags usage, VkImageLayout layout, Attachment* attachment = NULL );
};
}
}

View File

@ -10,23 +10,19 @@ namespace ext {
VkSurfaceKHR surface;
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
VkSemaphore presentCompleteSemaphore;
VkSemaphore renderCompleteSemaphore;
std::vector<VkFence> waitFences;
bool commandBufferSet = false;
std::vector<VkCommandBuffer> drawCommandBuffers;
bool initialized = false;
bool vsync = true;
uint32_t buffers;
VkSemaphore presentCompleteSemaphore;
VkSemaphore renderCompleteSemaphore;
// helpers
VkResult acquireNextImage( uint32_t *imageIndex );
VkResult acquireNextImage( uint32_t* imageIndex, VkSemaphore );
VkResult queuePresent( VkQueue queue, uint32_t imageIndex, VkSemaphore waitSemaphore = VK_NULL_HANDLE );
// RAII
void initialize( Device& device, size_t width = 0, size_t height = 0, bool vsync = true );
void initialize( Device& device );
void destroy();
};
}

View File

@ -46,7 +46,7 @@ namespace ext {
extern UF_API Swapchain swapchain;
extern UF_API std::mutex mutex;
extern UF_API bool resizedFramebuffer;
extern UF_API bool rebuild;
extern UF_API uint32_t currentBuffer;
extern UF_API std::string currentPass;
@ -56,7 +56,7 @@ namespace ext {
extern UF_API std::vector<uf::Scene*> scenes;
RenderMode& UF_API addRenderMode( RenderMode*, const std::string& = "" );
RenderMode& UF_API getRenderMode( const std::string& );
RenderMode& UF_API getRenderMode( const std::string&, bool = true );
void UF_API initialize( uint8_t = 0 );
void UF_API tick();

View File

@ -6,7 +6,7 @@ void uf::Scene::initialize() {
// this->m_graphics = new std::vector<ext::vulkan::Graphic*>();
// ext::vulkan::graphics = (std::vector<ext::vulkan::Graphic*>*) this->m_graphics;
ext::vulkan::scenes.push_back(this);
ext::vulkan::swapchain.rebuild = true;
ext::vulkan::rebuild = true;
uf::Object::initialize();
}
void uf::Scene::tick() {
@ -32,7 +32,7 @@ void uf::Scene::destroy() {
ext::vulkan::scenes.end()
);
*/
ext::vulkan::swapchain.rebuild = true;
ext::vulkan::rebuild = true;
/*
std::vector<ext::vulkan::Graphic*>* graphics = (std::vector<ext::vulkan::Graphic*>*) this->m_graphics;
for ( auto* graphic : *graphics ) {

View File

@ -216,7 +216,8 @@ void ext::openvr::tick() {
}
void ext::openvr::submit() {
ext::vulkan::MultiviewRenderMode* renderMode = (ext::vulkan::MultiviewRenderMode*) ext::vulkan::renderModes[0];
/*
// ext::vulkan::MultiviewRenderMode* renderMode = (ext::vulkan::MultiviewRenderMode*) ext::vulkan::renderModes[0];
float width = renderMode->width > 0 ? renderMode->width : ext::vulkan::width;
float height = renderMode->height > 0 ? renderMode->height : ext::vulkan::height;
// Submit to SteamVR
@ -248,6 +249,7 @@ void ext::openvr::submit() {
vr::VRCompositor()->Submit( vr::Eye_Right, &texture, &bounds );
vr::VRCompositor()->PostPresentHandoff();
*/
}
void ext::openvr::recommendedResolution( uint32_t& width, uint32_t& height ) {

View File

@ -103,12 +103,12 @@ VkResult ext::vulkan::Buffer::invalidate( VkDeviceSize size, VkDeviceSize offset
}
void ext::vulkan::Buffer::allocate( VkBufferCreateInfo bufferCreateInfo ) {
VK_CHECK_RESULT(vkCreateBuffer( device, &bufferCreateInfo, nullptr, &buffer));
// VK_CHECK_RESULT(vkCreateBuffer( device, &bufferCreateInfo, nullptr, &buffer));
VmaAllocationCreateInfo allocCreateInfo = {};
allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
allocCreateInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
if ( bufferCreateInfo.usage | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT ) {
if ( bufferCreateInfo.usage & (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT) ) {
allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
}

View File

@ -156,6 +156,8 @@ VkResult ext::vulkan::Device::createBuffer( VkBufferUsageFlags usageFlags, VkMem
memAlloc.allocationSize = memReqs.size;
// Find a memory type index that fits the properties of the buffer
memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags);
std::cout << "Allocating Memory: " << memory << std::endl;
VK_CHECK_RESULT( vkAllocateMemory(logicalDevice, &memAlloc, nullptr, memory));
// If a pointer to the buffer data has been passed, map the buffer and copy over the data
@ -189,10 +191,13 @@ VkResult ext::vulkan::Device::createBuffer(
void *data
) {
buffer.device = logicalDevice;
buffer.usageFlags = usageFlags;
buffer.memoryPropertyFlags = memoryPropertyFlags;
// Create the buffer handle
VkBufferCreateInfo bufferCreateInfo = ext::vulkan::initializers::bufferCreateInfo(usageFlags, size);
buffer.allocate( bufferCreateInfo );
/*
// VK_CHECK_RESULT(vkCreateBuffer(logicalDevice, &bufferCreateInfo, nullptr, &buffer.buffer));
// Create the memory backing up the buffer handle
@ -538,16 +543,16 @@ void ext::vulkan::Device::initialize() {
// If the surface format list only includes one entry with VK_FORMAT_UNDEFINED,
// there is no preferered format, so we assume VK_FORMAT_B8G8R8A8_UNORM
if ( (formatCount == 1) && (formats[0].format == VK_FORMAT_UNDEFINED) ) {
formats.color = VK_FORMAT_B8G8R8A8_UNORM;
formats.space = formats[0].colorSpace;
this->formats.color = VK_FORMAT_B8G8R8A8_UNORM;
this->formats.space = formats[0].colorSpace;
} else {
// iterate over the list of available surface format and
// check for the presence of VK_FORMAT_B8G8R8A8_UNORM
bool found_B8G8R8A8_UNORM = false;
for ( auto&& surfaceFormat : formats ) {
if ( surfaceFormat.format == VK_FORMAT_B8G8R8A8_UNORM ) {
formats.color = surfaceFormat.format;
formats.space = surfaceFormat.colorSpace;
this->formats.color = surfaceFormat.format;
this->formats.space = surfaceFormat.colorSpace;
found_B8G8R8A8_UNORM = true;
break;
}
@ -555,8 +560,8 @@ void ext::vulkan::Device::initialize() {
// in case VK_FORMAT_B8G8R8A8_UNORM is not available
// select the first available color format
if ( !found_B8G8R8A8_UNORM ) {
formats.color = formats[0].format;
formats.space = formats[0].colorSpace;
this->formats.color = formats[0].format;
this->formats.space = formats[0].colorSpace;
}
}
}
@ -577,7 +582,7 @@ void ext::vulkan::Device::initialize() {
vkGetPhysicalDeviceFormatProperties( this->physicalDevice, format, &formatProps );
// Format must support depth stencil attachment for optimal tiling
if (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
formats.depth = format;
this->formats.depth = format;
}
}
}

View File

@ -161,7 +161,7 @@ bool ext::vulkan::Graphic::autoAssignable() const {
}
void ext::vulkan::Graphic::autoAssign() {
if ( !autoAssigned ) {
swapchain.rebuild = true;
ext::vulkan::rebuild = true;
/*
ext::vulkan::graphics->push_back(this);
*/
@ -196,7 +196,7 @@ void ext::vulkan::Graphic::destroy() {
);
*/
autoAssigned = false;
swapchain.rebuild = true;
ext::vulkan::rebuild = true;
}
initialized = false;
if ( !device || device == VK_NULL_HANDLE ) return;

View File

@ -98,13 +98,31 @@ void ext::vulkan::BaseGraphic::initialize( Device& device, RenderMode& renderMod
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
false
);
// Swap buffers
// Move uniform buffer to the front
{
for ( auto it = buffers.begin(); it != buffers.end(); ++it ) {
Buffer& buffer = *it;
if ( !(buffer.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ) continue;
Buffer uniformBuffer = std::move(buffer);
buffers.erase(it);
buffers.insert( buffers.begin(), std::move(uniformBuffer) );
break;
}
}
/*
buffers = {
std::move(buffers.at(2)),
std::move(buffers.at(0)),
std::move(buffers.at(1)),
};
*/
/*
std::cout << "Buffers for " << this << "(" << this->name() << ")" << std::endl;
for ( std::size_t i = 0; i < buffers.size(); ++i ) {
auto& buffer = buffers[i];
std::cout << i << ": " << buffer.buffer << ": " << std::hex << buffer.usageFlags << std::endl;
}
*/
// set pipeline
{
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = ext::vulkan::initializers::pipelineInputAssemblyStateCreateInfo(
@ -119,13 +137,6 @@ void ext::vulkan::BaseGraphic::initialize( Device& device, RenderMode& renderMod
VK_FRONT_FACE_CLOCKWISE,
0
);
/*
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
0xf,
VK_FALSE
);
*/
/*
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
@ -138,21 +149,44 @@ void ext::vulkan::BaseGraphic::initialize( Device& device, RenderMode& renderMod
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
VkPipelineColorBlendStateCreateInfo colorBlendState = ext::vulkan::initializers::pipelineColorBlendStateCreateInfo(
1,
&blendAttachmentState
);
*/
std::vector<VkPipelineColorBlendAttachmentState> blendAttachmentStates;
for ( auto& attachment : renderMode.getFramebuffer().attachments ) {
if ( attachment.layout == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
/*
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
0xf,
VK_FALSE
);
VkPipelineColorBlendStateCreateInfo colorBlendState = ext::vulkan::initializers::pipelineColorBlendStateCreateInfo(
1,
&blendAttachmentState
);
*/
std::vector<VkPipelineColorBlendAttachmentState> blendAttachmentStates;
for ( auto& attachment : renderMode.renderTarget.attachments ) {
if ( attachment.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
0xf,
VK_TRUE
);
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
blendAttachmentStates.push_back(blendAttachmentState);
}
}
VkPipelineColorBlendStateCreateInfo colorBlendState = ext::vulkan::initializers::pipelineColorBlendStateCreateInfo(
blendAttachmentStates.size(),
renderMode.getType() == "Swapchain" ? 1 : blendAttachmentStates.size(),
blendAttachmentStates.data()
);
/*
colorBlendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlendState.logicOpEnable = VK_FALSE;
colorBlendState.logicOp = VK_LOGIC_OP_COPY;
@ -160,6 +194,7 @@ void ext::vulkan::BaseGraphic::initialize( Device& device, RenderMode& renderMod
colorBlendState.blendConstants[1] = 0.0f;
colorBlendState.blendConstants[2] = 0.0f;
colorBlendState.blendConstants[3] = 0.0f;
*/
VkPipelineDepthStencilStateCreateInfo depthStencilState = ext::vulkan::initializers::pipelineDepthStencilStateCreateInfo(
VK_TRUE,
VK_TRUE,
@ -211,7 +246,7 @@ void ext::vulkan::BaseGraphic::initialize( Device& device, RenderMode& renderMod
VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo(
pipelineLayout,
renderMode.getRenderPass(),
renderMode.renderTarget.renderPass,
0
);

View File

@ -356,7 +356,7 @@ void ext::vulkan::RTGraphic::initialize( Device& device, RenderMode& renderMode
VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo(
pipelineLayout,
renderMode.getRenderPass(),
renderMode.renderTarget.renderPass,
0
);
VkPipelineVertexInputStateCreateInfo emptyInputState = {};

View File

@ -126,12 +126,25 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, RenderMode& re
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
false
);
// Swap buffers
// Move uniform buffer to the front
{
for ( auto it = buffers.begin(); it != buffers.end(); ++it ) {
Buffer& buffer = *it;
if ( !(buffer.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ) continue;
Buffer uniformBuffer = std::move(buffer);
buffers.erase(it);
buffers.insert( buffers.begin(), std::move(uniformBuffer) );
break;
}
}
/*
buffers = {
std::move(buffers.at(2)),
std::move(buffers.at(0)),
std::move(buffers.at(1)),
};
*/
// set pipeline
{
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = ext::vulkan::initializers::pipelineInputAssemblyStateCreateInfo(
@ -145,6 +158,21 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, RenderMode& re
VK_FRONT_FACE_COUNTER_CLOCKWISE,
0
);
std::vector<VkPipelineColorBlendAttachmentState> blendAttachmentStates;
for ( auto& attachment : renderMode.renderTarget.attachments ) {
if ( attachment.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
0xf,
VK_FALSE
);
blendAttachmentStates.push_back(blendAttachmentState);
}
}
VkPipelineColorBlendStateCreateInfo colorBlendState = ext::vulkan::initializers::pipelineColorBlendStateCreateInfo(
blendAttachmentStates.size(),
blendAttachmentStates.data()
);
/*
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
0xf,
VK_FALSE
@ -153,6 +181,7 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, RenderMode& re
1,
&blendAttachmentState
);
*/
VkPipelineDepthStencilStateCreateInfo depthStencilState = ext::vulkan::initializers::pipelineDepthStencilStateCreateInfo(
VK_TRUE,
VK_TRUE,
@ -210,7 +239,7 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, RenderMode& re
VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo(
pipelineLayout,
renderMode.getRenderPass(),
renderMode.renderTarget.renderPass,
0
);
pipelineCreateInfo.pVertexInputState = &vertexInputState;
@ -235,7 +264,7 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, RenderMode& re
// Set descriptor set
{
VkDescriptorImageInfo textDescriptorAlbedo = ext::vulkan::initializers::descriptorImageInfo(
framebuffer->attachments[0].view,
renderTarget->attachments[0].view,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
);

View File

@ -62,11 +62,25 @@ void ext::vulkan::GuiGraphic::initialize( Device& device, RenderMode& renderMode
false
);
// Swap buffers
// Move uniform buffer to the front
{
for ( auto it = buffers.begin(); it != buffers.end(); ++it ) {
Buffer& buffer = *it;
if ( !(buffer.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ) continue;
Buffer uniformBuffer = std::move(buffer);
buffers.erase(it);
buffers.insert( buffers.begin(), std::move(uniformBuffer) );
break;
}
}
/*
buffers = {
std::move(buffers.at(2)),
std::move(buffers.at(0)),
std::move(buffers.at(1)),
};
*/
// check
// set pipeline
@ -163,7 +177,7 @@ void ext::vulkan::GuiGraphic::initialize( Device& device, RenderMode& renderMode
VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo(
pipelineLayout,
renderMode.getRenderPass(),
renderMode.renderTarget.renderPass,
0
);
pipelineCreateInfo.pVertexInputState = &vertexInputState;

View File

@ -58,12 +58,25 @@ void ext::vulkan::MeshGraphic::initialize( Device& device, RenderMode& renderMod
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
false
);
// Swap buffers
// Move uniform buffer to the front
{
for ( auto it = buffers.begin(); it != buffers.end(); ++it ) {
Buffer& buffer = *it;
if ( !(buffer.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ) continue;
Buffer uniformBuffer = std::move(buffer);
buffers.erase(it);
buffers.insert( buffers.begin(), std::move(uniformBuffer) );
break;
}
}
/*
buffers = {
std::move(buffers.at(2)),
std::move(buffers.at(0)),
std::move(buffers.at(1)),
};
*/
// check
/*
@ -169,7 +182,7 @@ void ext::vulkan::MeshGraphic::initialize( Device& device, RenderMode& renderMod
VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo(
pipelineLayout,
renderMode.getRenderPass(),
renderMode.renderTarget.renderPass,
0
);
pipelineCreateInfo.pVertexInputState = &vertexInputState;

View File

@ -118,11 +118,25 @@ void ext::vulkan::RenderTargetGraphic::initialize( Device& device, RenderMode& r
false
);
// Swap buffers
// Move uniform buffer to the front
{
for ( auto it = buffers.begin(); it != buffers.end(); ++it ) {
Buffer& buffer = *it;
if ( !(buffer.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ) continue;
Buffer uniformBuffer = std::move(buffer);
buffers.erase(it);
buffers.insert( buffers.begin(), std::move(uniformBuffer) );
break;
}
}
/*
buffers = {
std::move(buffers.at(2)),
std::move(buffers.at(0)),
std::move(buffers.at(1)),
};
*/
// set pipeline
{
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = ext::vulkan::initializers::pipelineInputAssemblyStateCreateInfo(
@ -136,11 +150,30 @@ void ext::vulkan::RenderTargetGraphic::initialize( Device& device, RenderMode& r
VK_FRONT_FACE_COUNTER_CLOCKWISE,
0
);
std::vector<VkPipelineColorBlendAttachmentState> blendAttachmentStates;
for ( auto& attachment : renderMode.renderTarget.attachments ) {
if ( attachment.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
0xf,
VK_FALSE
);
blendAttachmentStates.push_back(blendAttachmentState);
}
}
VkPipelineColorBlendStateCreateInfo colorBlendState = ext::vulkan::initializers::pipelineColorBlendStateCreateInfo(
blendAttachmentStates.size(),
blendAttachmentStates.data()
);
/*
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
0xf,
VK_FALSE
);
VkPipelineColorBlendStateCreateInfo colorBlendState = ext::vulkan::initializers::pipelineColorBlendStateCreateInfo(
1,
&blendAttachmentState
);
*/
/*
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
// VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
@ -159,10 +192,11 @@ void ext::vulkan::RenderTargetGraphic::initialize( Device& device, RenderMode& r
&blendAttachmentState
);
*/
/*
std::vector<VkPipelineColorBlendAttachmentState> blendAttachmentStates;
for ( auto& attachment : renderMode.framebuffer->attachments ) {
for ( auto& attachment : renderMode.renderTarget.attachments ) {
if ( attachment.layout == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
0xf,
VK_FALSE
);
@ -180,7 +214,7 @@ void ext::vulkan::RenderTargetGraphic::initialize( Device& device, RenderMode& r
colorBlendState.blendConstants[1] = 0.0f;
colorBlendState.blendConstants[2] = 0.0f;
colorBlendState.blendConstants[3] = 0.0f;
*/
VkPipelineDepthStencilStateCreateInfo depthStencilState = ext::vulkan::initializers::pipelineDepthStencilStateCreateInfo(
VK_TRUE,
VK_TRUE,
@ -238,7 +272,7 @@ void ext::vulkan::RenderTargetGraphic::initialize( Device& device, RenderMode& r
VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo(
pipelineLayout,
renderMode.getRenderPass(),
renderMode.renderTarget.renderPass,
0
);
pipelineCreateInfo.pVertexInputState = &vertexInputState;
@ -263,7 +297,7 @@ void ext::vulkan::RenderTargetGraphic::initialize( Device& device, RenderMode& r
// Set descriptor set
{
VkDescriptorImageInfo renderTargetDescriptor = ext::vulkan::initializers::descriptorImageInfo(
framebuffer->attachments[0].view,
renderTarget->attachments[0].view,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
sampler
);

View File

@ -20,9 +20,6 @@ const std::string& ext::vulkan::RenderMode::getName() const {
size_t ext::vulkan::RenderMode::subpasses() const {
return 1;
}
VkRenderPass& ext::vulkan::RenderMode::getRenderPass() {
return swapchain.renderPass;
}
void ext::vulkan::RenderMode::createCommandBuffers() {
std::vector<ext::vulkan::Graphic*> graphics;
@ -43,87 +40,15 @@ void ext::vulkan::RenderMode::createCommandBuffers() {
createCommandBuffers( graphics, ext::vulkan::passes );
}
void ext::vulkan::RenderMode::createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics, const std::vector<std::string>& passes ) {
// destroy if exists
if ( swapchain.initialized ) {
auto* device = swapchain.device;
bool vsync = swapchain.vsync;
swapchain.destroy();
swapchain.initialize( *device );
}
float width = width > 0 ? this->width : ext::vulkan::width;
float height = height > 0 ? this->height : ext::vulkan::height;
VkCommandBufferBeginInfo commandBufferInfo = {};
commandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
commandBufferInfo.pNext = nullptr;
// Set clear values for all framebuffer attachments with loadOp set to clear
// We use two attachments (color and depth) that are cleared at the start of the subpass and as such we need to set clear values for both
VkClearValue clearValues[2];
clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } };
clearValues[1].depthStencil = { 1.0f, 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 = width;
renderPassBeginInfo.clearValueCount = 2;
renderPassBeginInfo.pClearValues = clearValues;
for (size_t i = 0; i < commands.size(); ++i) {
// Set target frame buffer
renderPassBeginInfo.framebuffer = renderTarget.framebuffers[i];
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &commandBufferInfo));
for ( auto graphic : graphics ) {
graphic->createImageMemoryBarrier(commands[i]);
}
// Start the first sub pass specified in our default render pass setup by the base class
// This will clear the color and depth attachment
vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
// Update dynamic viewport state
VkViewport viewport = {};
viewport.height = (float) height;
viewport.width = (float) width;
viewport.minDepth = (float) 0.0f;
viewport.maxDepth = (float) 1.0f;
vkCmdSetViewport(commands[i], 0, 1, &viewport);
// Update dynamic scissor state
VkRect2D scissor = {};
scissor.extent.width = width;
scissor.extent.height = height;
scissor.offset.x = 0;
scissor.offset.y = 0;
vkCmdSetScissor(commands[i], 0, 1, &scissor);
for ( auto pass : passes ) {
ext::vulkan::currentPass = pass;
for ( auto graphic : graphics ) {
graphic->createCommandBuffer(commands[i] );
}
}
vkCmdEndRenderPass(commands[i]);
// Ending the render pass will add an implicit barrier transitioning the frame buffer color attachment to
// VK_IMAGE_LAYOUT_PRESENT_SRC_KHR for presenting it to the windowing system
VK_CHECK_RESULT(vkEndCommandBuffer(commands[i]));
}
}
void ext::vulkan::RenderMode::render() {
// Get next image in the swap chain (back/front buffer)
VK_CHECK_RESULT(swapchain.acquireNextImage(&currentBuffer));
VK_CHECK_RESULT(swapchain.acquireNextImage(&currentBuffer, swapchain.presentCompleteSemaphore));
// Use a fence to wait until the command buffer has finished execution before using it again
VK_CHECK_RESULT(vkWaitForFences(*device, 1, &waitFences[currentBuffer], VK_TRUE, UINT64_MAX));
VK_CHECK_RESULT(vkResetFences(*device, 1, &waitFences[currentBuffer]));
VK_CHECK_RESULT(vkWaitForFences(*device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX));
VK_CHECK_RESULT(vkResetFences(*device, 1, &fences[currentBuffer]));
// Pipeline stage at which the queue submission will wait (via pWaitSemaphores)
VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
@ -131,20 +56,20 @@ void ext::vulkan::RenderMode::render() {
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = &waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitSemaphores = &presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.pWaitSemaphores = &swapchain.presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.waitSemaphoreCount = 1; // One wait semaphore
submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.pSignalSemaphores = &swapchain.renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.signalSemaphoreCount = 1; // One signal semaphore
submitInfo.pCommandBuffers = &commands[currentBuffer]; // Command buffers(s) to execute in this batch (submission)
submitInfo.commandBufferCount = 1;
// Submit to the graphics queue passing a wait fence
VK_CHECK_RESULT(vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, waitFences[currentBuffer]));
VK_CHECK_RESULT(vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, fences[currentBuffer]));
// Present the current buffer to the swap chain
// Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation
// This ensures that the image is not presented to the windowing system until all commands have been submitted
VK_CHECK_RESULT(swapchain.queuePresent(device->presentQueue, currentBuffer, renderCompleteSemaphore));
VK_CHECK_RESULT(swapchain.queuePresent(device->presentQueue, currentBuffer, swapchain.renderCompleteSemaphore));
VK_CHECK_RESULT(vkQueueWaitIdle(device->presentQueue));
}
@ -156,36 +81,25 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
// Create command buffers
{
drawCommandBuffers.resize( buffers );
commands.resize( swapchain.buffers );
VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo(
device.commandPool,
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
static_cast<uint32_t>(drawCommandBuffers.size())
static_cast<uint32_t>(commands.size())
);
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, drawCommandBuffers.data()));
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, commands.data()));
}
// Set sync objects
{
// Semaphores (Used for correct command ordering)
VkSemaphoreCreateInfo semaphoreCreateInfo = {};
semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
semaphoreCreateInfo.pNext = nullptr;
// Semaphore used to ensures that image presentation is complete before starting to submit again
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &presentCompleteSemaphore));
// Semaphore used to ensures that all commands submitted have been finished before submitting the image to the queue
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &renderCompleteSemaphore));
// Fences (Used to check draw command buffer completion)
VkFenceCreateInfo fenceCreateInfo = {};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
// Create in signaled state so we don't wait on first render of each command buffer
fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
waitFences.resize( buffers );
for ( auto& fence : waitFences ) {
fences.resize( commands.size() );
for ( auto& fence : fences ) {
VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence));
}
@ -194,13 +108,14 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
}
void ext::vulkan::RenderMode::destroy() {
renderTarget.destroy();
if ( commands.size() > 0 ) {
vkFreeCommandBuffers( *device, device->commandPool, static_cast<uint32_t>(commands.size()), commands.data());
}
if ( presentCompleteSemaphore != VK_NULL_HANDLE ) {
vkDestroySemaphore( *device, presentCompleteSemaphore, nullptr);
}
if ( renderCompleteSemaphore != VK_NULL_HANDLE ) {
vkDestroySemaphore( *device, renderCompleteSemaphore, nullptr);
for ( auto& fence : fences ) {
vkDestroyFence( *device, fence, nullptr);
fence = VK_NULL_HANDLE;
}
}

View File

@ -6,13 +6,17 @@
#include <uf/ext/vulkan/rendertarget.h>
#include <uf/utils/mesh/mesh.h>
namespace {
std::vector<VkImage> images;
}
/*
ext::vulkan::BaseRenderMode::~BaseRenderMode() {
this->destroy();
}
*/
std::string ext::vulkan::BaseRenderMode::getType() const {
return "Base";
return "Swapchain";
}
const std::string& ext::vulkan::BaseRenderMode::getName() const {
return this->name;
@ -20,36 +24,14 @@ const std::string& ext::vulkan::BaseRenderMode::getName() const {
size_t ext::vulkan::BaseRenderMode::subpasses() const {
return 1;
}
VkRenderPass& ext::vulkan::BaseRenderMode::getRenderPass() {
return swapchain.renderPass;
}
void ext::vulkan::BaseRenderMode::createCommandBuffers() {
std::vector<ext::vulkan::Graphic*> graphics;
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
if ( !entity->hasComponent<uf::Mesh>() ) return;
uf::MeshBase& mesh = entity->getComponent<uf::Mesh>();
if ( !mesh.generated ) return;
ext::vulkan::Graphic& graphic = mesh.graphic;
if ( !graphic.initialized ) return;
if ( !graphic.renderMode ) return;
graphics.push_back(&graphic);
};
for ( uf::Scene* scene : ext::vulkan::scenes ) {
if ( !scene ) continue;
scene->process(filter);
}
createCommandBuffers( graphics, ext::vulkan::passes );
}
void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics, const std::vector<std::string>& passes ) {
// destroy if exists
if ( swapchain.initialized ) {
auto* device = swapchain.device;
bool vsync = swapchain.vsync;
swapchain.destroy();
swapchain.initialize( *device );
if ( ext::vulkan::rebuild ) {
this->destroy();
this->initialize( *this->device );
}
renderTarget.initialized = true;
if ( ext::vulkan::renderModes.size() > 1 ) return;
float width = width > 0 ? this->width : ext::vulkan::width;
float height = height > 0 ? this->height : ext::vulkan::height;
@ -71,7 +53,7 @@ void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vector<ext::v
renderPassBeginInfo.renderArea.offset.x = 0;
renderPassBeginInfo.renderArea.offset.y = 0;
renderPassBeginInfo.renderArea.extent.width = width;
renderPassBeginInfo.renderArea.extent.height = width;
renderPassBeginInfo.renderArea.extent.height = height;
renderPassBeginInfo.clearValueCount = 2;
renderPassBeginInfo.pClearValues = clearValues;
for (size_t i = 0; i < commands.size(); ++i) {
@ -118,42 +100,214 @@ void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vector<ext::v
}
void ext::vulkan::BaseRenderMode::render() {
// Get next image in the swap chain (back/front buffer)
VK_CHECK_RESULT(swapchain.acquireNextImage(&currentBuffer));
// Use a fence to wait until the command buffer has finished execution before using it again
VK_CHECK_RESULT(vkWaitForFences(*device, 1, &waitFences[currentBuffer], VK_TRUE, UINT64_MAX));
VK_CHECK_RESULT(vkResetFences(*device, 1, &waitFences[currentBuffer]));
// Pipeline stage at which the queue submission will wait (via pWaitSemaphores)
VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
// The submit info structure specifices a command buffer queue submission batch
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = &waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitSemaphores = &presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.waitSemaphoreCount = 1; // One wait semaphore
submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.signalSemaphoreCount = 1; // One signal semaphore
submitInfo.pCommandBuffers = &commands[currentBuffer]; // Command buffers(s) to execute in this batch (submission)
submitInfo.commandBufferCount = 1;
// Submit to the graphics queue passing a wait fence
VK_CHECK_RESULT(vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, waitFences[currentBuffer]));
// Present the current buffer to the swap chain
// Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation
// This ensures that the image is not presented to the windowing system until all commands have been submitted
VK_CHECK_RESULT(swapchain.queuePresent(device->presentQueue, currentBuffer, renderCompleteSemaphore));
VK_CHECK_RESULT(vkQueueWaitIdle(device->presentQueue));
if ( ext::vulkan::renderModes.size() > 1 ) return;
ext::vulkan::RenderMode::render();
}
void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
this->device = &device;
this->name = "Swapchain";
ext::vulkan::RenderMode::initialize( device );
// manual initialization
// recreate swapchain
// destroy any existing imageviews
// attachments marked as aliased are actually from the swapchain
this->width = ext::vulkan::width;
this->height = ext::vulkan::height;
swapchain.destroy();
swapchain.initialize( device );
// bind swapchain images
images.resize( ext::vulkan::swapchain.buffers );
VK_CHECK_RESULT(vkGetSwapchainImagesKHR( device, swapchain.swapChain, &swapchain.buffers, images.data()));
// create image views for swapchain images
renderTarget.attachments.clear();
renderTarget.attachments.resize( ext::vulkan::swapchain.buffers + 1 );
for ( size_t i = 0; i < images.size(); ++i ) {
VkImageViewCreateInfo colorAttachmentView = {};
colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
colorAttachmentView.pNext = NULL;
colorAttachmentView.format = device.formats.color;
colorAttachmentView.components = {
VK_COMPONENT_SWIZZLE_R,
VK_COMPONENT_SWIZZLE_G,
VK_COMPONENT_SWIZZLE_B,
VK_COMPONENT_SWIZZLE_A
};
colorAttachmentView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
colorAttachmentView.subresourceRange.baseMipLevel = 0;
colorAttachmentView.subresourceRange.levelCount = 1;
colorAttachmentView.subresourceRange.baseArrayLayer = 0;
colorAttachmentView.subresourceRange.layerCount = 1;
colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D;
colorAttachmentView.flags = 0;
colorAttachmentView.image = images[i];
VK_CHECK_RESULT(vkCreateImageView( device, &colorAttachmentView, nullptr, &renderTarget.attachments[i].view));
renderTarget.attachments[i].image = images[i];
renderTarget.attachments[i].format = device.formats.color;
renderTarget.attachments[i].layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
renderTarget.attachments[i].usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
renderTarget.attachments[i].aliased = true;
renderTarget.attachments[i].mem = VK_NULL_HANDLE;
}
// Create depth
auto& depthAttachment = renderTarget.attachments.back();
{
// Create an optimal image used as the depth stencil attachment
VkImageCreateInfo image = {};
image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
image.imageType = VK_IMAGE_TYPE_2D;
image.format = device.formats.depth;
// Use example's height and width
image.extent = { width, height, 1 };
image.mipLevels = 1;
image.arrayLayers = 1;
image.samples = VK_SAMPLE_COUNT_1_BIT;
image.tiling = VK_IMAGE_TILING_OPTIMAL;
image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &depthAttachment.image));
// Allocate memory for the image (device local) and bind it to our image
VkMemoryAllocateInfo memAlloc = {};
memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
VkMemoryRequirements memReqs;
vkGetImageMemoryRequirements(device, depthAttachment.image, &memReqs);
memAlloc.allocationSize = memReqs.size;
memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &depthAttachment.mem));
VK_CHECK_RESULT(vkBindImageMemory(device, depthAttachment.image, depthAttachment.mem, 0));
// Create a view for the depth stencil image
// Images aren't directly accessed in Vulkan, but rather through views described by a subresource range
// This allows for multiple views of one image with differing ranges (e.g. for different layers)
VkImageViewCreateInfo depthStencilView = {};
depthStencilView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D;
depthStencilView.format = device.formats.depth;
depthStencilView.subresourceRange = {};
depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
depthStencilView.subresourceRange.baseMipLevel = 0;
depthStencilView.subresourceRange.levelCount = 1;
depthStencilView.subresourceRange.baseArrayLayer = 0;
depthStencilView.subresourceRange.layerCount = 1;
depthStencilView.image = depthAttachment.image;
VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &depthAttachment.view));
}
// Create renderpass
if ( !renderTarget.renderPass ) {// Create render pass
// This example will use a single render pass with one subpass
// Descriptors for the attachments used by this renderpass
std::array<VkAttachmentDescription, 2> attachments = {};
// Color attachment
attachments[0].format = device.formats.color; // Use the color format selected by the swapchain
attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; // We don't use multi sampling in this example
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear this attachment at the start of the render pass
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // Keep it's contents after the render pass is finished (for displaying it)
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // We don't use stencil, so don't care for load
attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // Same for store
attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Layout at render pass start. Initial doesn't matter, so we use undefined
attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; // Layout to which the attachment is transitioned when the render pass is finished
// As we want to present the color buffer to the swapchain, we transition to PRESENT_KHR
// Depth attachment
attachments[1].format = device.formats.depth; // A proper depth format is selected in the example base
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear depth at start of first subpass
attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // We don't need depth after render pass has finished (DONT_CARE may result in better performance)
attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // No stencil
attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // No Stencil
attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Layout at render pass start. Initial doesn't matter, so we use undefined
attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // Transition to depth/stencil attachment
// Setup attachment references
VkAttachmentReference colorReference = {};
colorReference.attachment = 0; // Attachment 0 is color
colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // Attachment layout used as color during the subpass
VkAttachmentReference depthReference = {};
depthReference.attachment = 1; // Attachment 1 is color
depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // Attachment used as depth/stemcil used during the subpass
// Setup a single subpass reference
VkSubpassDescription subpassDescription = {};
subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpassDescription.colorAttachmentCount = 1; // Subpass uses one color attachment
subpassDescription.pColorAttachments = &colorReference; // Reference to the color attachment in slot 0
subpassDescription.pDepthStencilAttachment = &depthReference; // Reference to the depth attachment in slot 1
subpassDescription.inputAttachmentCount = 0; // Input attachments can be used to sample from contents of a previous subpass
subpassDescription.pInputAttachments = nullptr; // (Input attachments not used by this example)
subpassDescription.preserveAttachmentCount = 0; // Preserved attachments can be used to loop (and preserve) attachments through subpasses
subpassDescription.pPreserveAttachments = nullptr; // (Preserve attachments not used by this example)
subpassDescription.pResolveAttachments = nullptr; // Resolve attachments are resolved at the end of a sub pass and can be used for e.g. multi sampling
// Setup subpass dependencies
// These will add the implicit ttachment layout transitionss specified by the attachment descriptions
// The actual usage layout is preserved through the layout specified in the attachment reference
// Each subpass dependency will introduce a memory and execution dependency between the source and dest subpass described by
// srcStageMask, dstStageMask, srcAccessMask, dstAccessMask (and dependencyFlags is set)
// Note: VK_SUBPASS_EXTERNAL is a special constant that refers to all commands executed outside of the actual renderpass)
std::array<VkSubpassDependency, 2> dependencies;
// First dependency at the start of the renderpass
// Does the transition from final to initial layout
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; // Producer of the dependency
dependencies[0].dstSubpass = 0; // Consumer is our single subpass that will wait for the execution depdendency
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
// Second dependency at the end the renderpass
// Does the transition from the initial to the final layout
dependencies[1].srcSubpass = 0; // Producer of the dependency is our single subpass
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; // Consumer are all commands outside of the renderpass
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
// Create the actual renderpass
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size()); // Number of attachments used by this render pass
renderPassInfo.pAttachments = attachments.data(); // Descriptions of the attachments used by the render pass
renderPassInfo.subpassCount = 1; // We only use one subpass in this example
renderPassInfo.pSubpasses = &subpassDescription; // Description of that subpass
renderPassInfo.dependencyCount = static_cast<uint32_t>(dependencies.size()); // Number of subpass dependencies
renderPassInfo.pDependencies = dependencies.data(); // Subpass dependencies used by the render pass
VK_CHECK_RESULT(vkCreateRenderPass( device, &renderPassInfo, nullptr, &renderTarget.renderPass));
}
// Create framebuffer
{
// Create a frame buffer for every image in the swapchain
renderTarget.framebuffers.resize(images.size());
for (size_t i = 0; i < renderTarget.framebuffers.size(); i++)
{
std::array<VkImageView, 2> attachments;
attachments[0] = renderTarget.attachments[i].view; // Color attachment is the view of the swapchain image
attachments[1] = depthAttachment.view; // Depth/Stencil attachment is the same for all frame buffers
VkFramebufferCreateInfo frameBufferCreateInfo = {};
frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
// All frame buffers use the same renderpass setup
frameBufferCreateInfo.renderPass = renderTarget.renderPass;
frameBufferCreateInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
frameBufferCreateInfo.pAttachments = attachments.data();
frameBufferCreateInfo.width = width;
frameBufferCreateInfo.height = height;
frameBufferCreateInfo.layers = 1;
// Create the framebuffer
VK_CHECK_RESULT(vkCreateFramebuffer( device, &frameBufferCreateInfo, nullptr, &renderTarget.framebuffers[i]));
}
}
/*
{
renderTarget.device = &device;
// attach targets
@ -161,8 +315,10 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
size_t color, depth;
} attachments;
attachments.color = renderTarget.attach( device.formats.color, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ); // color
attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ); // depth
attachments.color = 0; {
}
attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ); // depth
// First pass: fill the G-Buffer
{
@ -175,19 +331,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
}
}
renderTarget.initialize( device );
// Create command buffers
{
commands.resize( buffers );
VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo(
device.commandPool,
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
static_cast<uint32_t>(commands.size())
);
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, commands.data()));
}
*/
// Set sync objects
{
// Semaphores (Used for correct command ordering)
@ -196,33 +340,47 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
semaphoreCreateInfo.pNext = nullptr;
// Semaphore used to ensures that image presentation is complete before starting to submit again
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &presentCompleteSemaphore));
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &swapchain.presentCompleteSemaphore));
// Semaphore used to ensures that all commands submitted have been finished before submitting the image to the queue
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &renderCompleteSemaphore));
// Fences (Used to check draw command buffer completion)
VkFenceCreateInfo fenceCreateInfo = {};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
// Create in signaled state so we don't wait on first render of each command buffer
fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
waitFences.resize( buffers );
for ( auto& fence : waitFences ) {
VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence));
}
VkPipelineStageFlags submitPipelineStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &swapchain.renderCompleteSemaphore));
}
}
void ext::vulkan::BaseRenderMode::destroy() {
if ( commands.size() > 0 ) {
vkFreeCommandBuffers( *device, device->commandPool, static_cast<uint32_t>(commands.size()), commands.data());
ext::vulkan::RenderMode::destroy();
if ( renderTarget.renderPass != VK_NULL_HANDLE ) {
vkDestroyRenderPass( *device, renderTarget.renderPass, nullptr );
renderTarget.renderPass = VK_NULL_HANDLE;
}
if ( presentCompleteSemaphore != VK_NULL_HANDLE ) {
vkDestroySemaphore( *device, presentCompleteSemaphore, nullptr);
}
if ( renderCompleteSemaphore != VK_NULL_HANDLE ) {
vkDestroySemaphore( *device, renderCompleteSemaphore, nullptr);
for ( uint32_t i = 0; i < renderTarget.framebuffers.size(); i++ ) {
if ( renderTarget.framebuffers[i] != VK_NULL_HANDLE ) {
vkDestroyFramebuffer( *device, renderTarget.framebuffers[i], nullptr );
renderTarget.framebuffers[i] = VK_NULL_HANDLE;
}
}
for ( auto& attachment : renderTarget.attachments ) {
if ( attachment.view != VK_NULL_HANDLE ) {
vkDestroyImageView( *device, attachment.view, nullptr);
attachment.view = VK_NULL_HANDLE;
}
if ( attachment.aliased ) continue;
if ( attachment.image != VK_NULL_HANDLE ) {
vkDestroyImage( *device, attachment.image, nullptr );
attachment.image = VK_NULL_HANDLE;
}
if ( attachment.mem != VK_NULL_HANDLE ) {
vkFreeMemory( *device, attachment.mem, nullptr );
attachment.mem = VK_NULL_HANDLE;
}
}
if ( swapchain.presentCompleteSemaphore != VK_NULL_HANDLE ) {
vkDestroySemaphore( *device, swapchain.presentCompleteSemaphore, nullptr);
}
if ( swapchain.renderCompleteSemaphore != VK_NULL_HANDLE ) {
vkDestroySemaphore( *device, swapchain.renderCompleteSemaphore, nullptr);
}
}

View File

@ -16,9 +16,6 @@ std::string ext::vulkan::DeferredRenderMode::getType() const {
size_t ext::vulkan::DeferredRenderMode::subpasses() const {
return renderTarget.passes.size();
}
VkRenderPass& ext::vulkan::DeferredRenderMode::getRenderPass() {
return renderTarget.renderPass;
}
void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
ext::vulkan::RenderMode::initialize( device );
@ -29,13 +26,18 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
size_t albedo, normals, depth, output;
} attachments;
attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ); // albedo
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ); // normals
attachments.depth = renderTarget.attach( swapchain.depthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ); // depth
attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // normals
attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ); // depth
// Attach swapchain's image as output
{
attachments.output = renderTarget.attachments.size();
renderTarget.attachments.push_back({ device.formats.color, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, });
RenderTarget::Attachment swapchainAttachment;
swapchainAttachment.format = device.formats.color;
swapchainAttachment.usage = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
swapchainAttachment.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
swapchainAttachment.aliased = true;
renderTarget.attachments.push_back(swapchainAttachment);
}
// First pass: fill the G-Buffer
@ -43,6 +45,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.albedo, attachments.normals, },
// { attachments.albedo },
{},
attachments.depth
);
@ -53,13 +56,14 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT,
{ attachments.output, },
{ attachments.albedo, attachments.normals },
// { attachments.albedo },
attachments.depth
);
}
}
renderTarget.initialize( device );
blitter.framebuffer = &framebuffer;
blitter.renderTarget = &renderTarget;
blitter.initializeShaders({
{"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
{"./data/shaders/display.subpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
@ -67,25 +71,18 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
blitter.initialize( device, *this );
}
void ext::vulkan::DeferredRenderMode::destroy() {
renderTarget.destroy();
ext::vulkan::RenderMode::destroy();
blitter.destroy();
}
void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics, const std::vector<std::string>& passes ) {
// destroy if exists
// ext::vulkan::RenderMode& swapchain =
if ( ext::vulkan::rebuild ) {
if ( swapchain.initialized ) {
auto* device = swapchain.device;
swapchain.destroy();
swapchain.initialize( *device );
}
swapchain.initialized = true;
// destroy if exist
if ( renderTarget.initialized ) {
{
auto* device = renderTarget.device;
renderTarget.initialize( *device );
}
renderTarget.initialized = true;
// update descriptor set
if ( blitter.initialized ) {
@ -109,7 +106,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
&textDescriptorAlbedo
),
};
vkUpdateDescriptorSets( *device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr );
blitter.initializeDescriptorSet( writeDescriptorSets );
}
}
@ -121,8 +118,8 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdBufInfo.pNext = nullptr;
for (int32_t i = 0; i < swapchain.commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(swapchain.commands[i], &cmdBufInfo));
for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
// Fill GBuffer
{
std::vector<VkClearValue> clearValues; clearValues.resize(4);
@ -144,7 +141,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
renderPassBeginInfo.framebuffer = renderTarget.framebuffers[i];
for ( auto graphic : graphics ) {
graphic->createImageMemoryBarrier(swapchain.commands[i]);
graphic->createImageMemoryBarrier(commands[i]);
}
// Update dynamic viewport state
@ -161,30 +158,30 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
scissor.offset.x = 0;
scissor.offset.y = 0;
vkCmdBeginRenderPass(swapchain.commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdSetViewport(swapchain.commands[i], 0, 1, &viewport);
vkCmdSetScissor(swapchain.commands[i], 0, 1, &scissor);
vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdSetViewport(commands[i], 0, 1, &viewport);
vkCmdSetScissor(commands[i], 0, 1, &scissor);
for ( auto pass : passes ) {
ext::vulkan::currentPass = pass + ";DEFERRED";
for ( auto graphic : graphics ) {
// only draw graphics that are assigned to this type of render mode
if ( graphic->renderMode->getName() != this->getName() ) continue;
graphic->createCommandBuffer(swapchain.commands[i] );
graphic->createCommandBuffer(commands[i] );
}
}
vkCmdNextSubpass(swapchain.commands[i], VK_SUBPASS_CONTENTS_INLINE);
blitter.createCommandBuffer(swapchain.commands[i]);
vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE);
blitter.createCommandBuffer(commands[i]);
// render gui layer
{
RenderMode* layer = &ext::vulkan::getRenderMode("Gui");
if ( layer->getName() == "Gui" ) {
RenderTargetRenderMode* guiLayer = (RenderTargetRenderMode*) layer;
guiLayer->blitter.createCommandBuffer(swapchain.commands[i]);
guiLayer->blitter.createCommandBuffer(commands[i]);
}
}
vkCmdEndRenderPass(swapchain.commands[i]);
vkCmdEndRenderPass(commands[i]);
}
VK_CHECK_RESULT(vkEndCommandBuffer(swapchain.commands[i]));
VK_CHECK_RESULT(vkEndCommandBuffer(commands[i]));
}
}

View File

@ -10,15 +10,16 @@ namespace {
uint8_t DOMINANT_EYE = 1;
}
ext::vulkan::MultiviewRenderMode::MultiviewRenderMode() : rendertargets.left( rendertarget ) {
}
std::string ext::vulkan::MultiviewRenderMode::getType() const {
return "Multiview";
}
size_t ext::vulkan::MultiviewRenderMode::subpasses() const {
return rendertargets.left.passes.size();
}
VkRenderPass& ext::vulkan::MultiviewRenderMode::getRenderPass() {
return rendertargets.left.renderPass;
}
void ext::vulkan::MultiviewRenderMode::initialize( Device& device ) {
rendertargets.left.initialize( device );

View File

@ -10,9 +10,6 @@ std::string ext::vulkan::RenderTargetRenderMode::getType() const {
size_t ext::vulkan::RenderTargetRenderMode::subpasses() const {
return renderTarget.passes.size();
}
VkRenderPass& ext::vulkan::RenderTargetRenderMode::getRenderPass() {
return renderTarget.renderPass;
}
void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
ext::vulkan::RenderMode::initialize( device );
@ -23,8 +20,8 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
size_t color, depth;
} attachments;
attachments.color = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ); // albedo
attachments.depth = renderTarget.attach( swapchain.depthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ); // depth
attachments.color = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ); // depth
// First pass: write to target
{
@ -38,58 +35,38 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
}
renderTarget.initialize( device );
blitter.framebuffer = &framebuffer;
blitter.renderTarget = &renderTarget;
blitter.initializeShaders({
{"./data/shaders/display.rendertarget.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
{"./data/shaders/display.rendertarget.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
});
blitter.initialize();
// Create command buffers
{
VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo(
device.commandPool,
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1
);
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &commandBuffer));
}
// Set sync objects
{
// Fence for syncs
VkFenceCreateInfo fenceCreateInfo = ext::vulkan::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT);
VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence));
}
}
void ext::vulkan::RenderTargetRenderMode::destroy() {
renderTarget.destroy();
if ( fence != VK_NULL_HANDLE ) {
vkDestroyFence(*device, fence, nullptr);
fence = VK_NULL_HANDLE;
}
ext::vulkan::RenderMode::destroy();
blitter.destroy();
}
void ext::vulkan::RenderTargetRenderMode::render() {
// Submit commands
// Use a fence to ensure that command buffer has finished executing before using it again
vkWaitForFences( *device, 1, &fence, VK_TRUE, UINT64_MAX );
vkResetFences( *device, 1, &fence );
vkWaitForFences( *device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX );
vkResetFences( *device, 1, &fences[currentBuffer] );
VkSubmitInfo renderSubmitInfo = ext::vulkan::initializers::submitInfo();
renderSubmitInfo.commandBufferCount = 1;
renderSubmitInfo.pCommandBuffers = &commandBuffer;
renderSubmitInfo.pCommandBuffers = &commands[currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(device->graphicsQueue, 1, &renderSubmitInfo, fence));
VK_CHECK_RESULT(vkQueueSubmit(device->graphicsQueue, 1, &renderSubmitInfo, fences[currentBuffer]));
}
void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics, const std::vector<std::string>& passes ) {
// destroy if exists
if ( swapchain.rebuild ) {
if ( ext::vulkan::rebuild ) {
// destroy if exist
if ( renderTarget.commandBufferSet ) {
if ( renderTarget.initialized ) {
auto* device = renderTarget.device;
renderTarget.initialize( *device );
}
renderTarget.commandBufferSet = true;
renderTarget.initialized = true;
// update descriptor set
if ( blitter.initialized ) {
@ -125,7 +102,8 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdBufInfo.pNext = nullptr;
VK_CHECK_RESULT(vkBeginCommandBuffer(commandBuffer, &cmdBufInfo));
for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
{
std::vector<VkClearValue> clearValues; clearValues.resize(2);
clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } };
@ -141,10 +119,10 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto
renderPassBeginInfo.clearValueCount = clearValues.size();
renderPassBeginInfo.pClearValues = &clearValues[0];
renderPassBeginInfo.renderPass = renderTarget.renderPass;
renderPassBeginInfo.framebuffer = renderTarget.framebuffers[0];
renderPassBeginInfo.framebuffer = renderTarget.framebuffers[i];
for ( auto graphic : graphics ) {
graphic.createImageMemoryBarrier(commandBuffer);
graphic->createImageMemoryBarrier(commands[i]);
}
// Update dynamic viewport state
@ -161,18 +139,19 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto
scissor.offset.x = 0;
scissor.offset.y = 0;
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdSetViewport(commands[i], 0, 1, &viewport);
vkCmdSetScissor(commands[i], 0, 1, &scissor);
for ( auto pass : passes ) {
ext::vulkan::currentPass = pass + ";TOTEXTURE";
for ( auto graphic : graphics ) {
if ( graphic->renderMode && graphic->renderMode->getName() != this->getName() ) continue;
graphic->createCommandBuffer(commandBuffer );
graphic->createCommandBuffer(commands[i] );
}
}
vkCmdEndRenderPass(commandBuffer);
vkCmdEndRenderPass(commands[i]);
}
VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer));
VK_CHECK_RESULT(vkEndCommandBuffer(commands[i]));
}
}

View File

@ -16,7 +16,7 @@ void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFla
if ( depth < attachments.size() ) pass.depth = { depth, attachments[depth].layout };
passes.push_back(pass);
}
size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usage, Attachment* attachment ) {
size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usage, VkImageLayout layout, Attachment* attachment ) {
if ( width == 0 ) width = ext::vulkan::width;
if ( height == 0 ) height = ext::vulkan::height;
@ -24,20 +24,29 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa
attachments.resize(attachments.size()+1);
attachment = &attachments.back();
} else {
if ( attachment->view ) {
vkDestroyImageView(*device, attachment->view, nullptr);
attachment->view = VK_NULL_HANDLE;
}
if ( attachment->image ) {
vkDestroyImage(*device, attachment->image, nullptr);
attachment->image = VK_NULL_HANDLE;
}
if ( attachment->mem ) {
vkFreeMemory(*device, attachment->mem, nullptr);
attachment->mem = VK_NULL_HANDLE;
}
}
VkImageAspectFlags aspectMask = 0;
// specialization: depth buffer
if ( usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; // | VK_IMAGE_ASPECT_STENCIL_BIT;
attachment->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
} else {
aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
attachment->layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
attachment->layout = layout;
attachment->format = format;
attachment->usage = usage;
@ -50,7 +59,7 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa
image.arrayLayers = USEVR ? 2 : 1;
image.samples = VK_SAMPLE_COUNT_1_BIT;
image.tiling = VK_IMAGE_TILING_OPTIMAL;
image.usage = usage | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
image.usage = usage;
image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VK_CHECK_RESULT(vkCreateImage(*device, &image, nullptr, &attachment->image));
@ -93,8 +102,8 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
// resize attachments if necessary
if ( initialized ) {
for ( auto& attachment: this->attachments ) {
if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue;
attach( attachment.format, attachment.usage, &attachment );
if ( attachment.aliased ) continue;
attach( attachment.format, attachment.usage, attachment.layout, &attachment );
}
}
// ensure attachments are already created
@ -168,16 +177,6 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
dependencies.push_back(dependency);
}
/*
std::cout << this << std::endl;
for ( auto& dependency : dependencies ) {
std::cout << "Subpass: " << std::hex << dependency.srcSubpass << " -> " << std::hex << dependency.dstSubpass << std::endl;;
std::cout << "StageMask: " << std::hex << dependency.srcStageMask << " -> " << std::hex << dependency.dstStageMask << std::endl;;
std::cout << "AccessMask: " << std::hex << dependency.srcAccessMask << " -> " << std::hex << dependency.dstAccessMask << std::endl;;
std::cout << std::endl;
}
*/
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.flags = 0;
@ -191,18 +190,18 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass));
}
// Create framebuffer
bool boundToSwapchain = false;
for ( auto& attachment : this->attachments ) {
if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) boundToSwapchain = true;
}
{
framebuffers.resize(boundToSwapchain ? swapchain.imageCount : 1);
// destroy previous framebuffers
for ( auto& framebuffer : framebuffers ) vkDestroyFramebuffer( device, framebuffer, nullptr );
RenderMode& base = ext::vulkan::getRenderMode( "Swapchain", false );
framebuffers.resize(ext::vulkan::swapchain.buffers);
for ( size_t i = 0; i < framebuffers.size(); ++i ) {
std::vector<VkImageView> attachments;
for ( auto& attachment : this->attachments ) {
if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) attachments.push_back(swapchain.buffers[i].view);
else attachments.push_back(attachment.view);
if ( attachment.aliased && attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) {
attachments.push_back(base.renderTarget.attachments[i].view);
} else attachments.push_back(attachment.view);
}
VkFramebufferCreateInfo frameBufferCreateInfo = {};
@ -218,6 +217,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
VK_CHECK_RESULT(vkCreateFramebuffer( device, &frameBufferCreateInfo, nullptr, &framebuffers[i]));
}
}
initialized = true;
}
void ext::vulkan::RenderTarget::destroy() {
@ -226,7 +226,7 @@ void ext::vulkan::RenderTarget::destroy() {
for ( auto& framebuffer : framebuffers ) vkDestroyFramebuffer( *device, framebuffer, nullptr );
for ( auto& attachment : attachments ) {
if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue;
if ( attachment.aliased ) continue;
vkDestroyImageView( *device, attachment.view, nullptr );
attachment.view = VK_NULL_HANDLE;
vkDestroyImage( *device, attachment.image, nullptr );

View File

@ -3,7 +3,7 @@
#include <uf/ext/vulkan/initializers.h>
#include <uf/utils/window/window.h>
VkResult ext::vulkan::Swapchain::acquireNextImage( uint32_t *imageIndex ) {
VkResult ext::vulkan::Swapchain::acquireNextImage( uint32_t* imageIndex, VkSemaphore presentCompleteSemaphore ) {
// By setting timeout to UINT64_MAX we will always wait until the next image has been acquired or an actual error is thrown
// With that we don't have to handle VK_NOT_READY
return vkAcquireNextImageKHR( *device, swapChain, UINT64_MAX, presentCompleteSemaphore, (VkFence) nullptr, imageIndex );
@ -121,8 +121,8 @@ void ext::vulkan::Swapchain::initialize( Device& device ) {
swapchainCI.pNext = NULL;
swapchainCI.surface = device.surface;
swapchainCI.minImageCount = desiredNumberOfSwapchainImages;
swapchainCI.imageFormat = device->formats.color;
swapchainCI.imageColorSpace = device->formats.space;
swapchainCI.imageFormat = device.formats.color;
swapchainCI.imageColorSpace = device.formats.space;
swapchainCI.imageExtent = { swapchainExtent.width, swapchainExtent.height };
swapchainCI.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swapchainCI.preTransform = (VkSurfaceTransformFlagBitsKHR)preTransform;
@ -162,13 +162,6 @@ void ext::vulkan::Swapchain::destroy() {
vkDestroySwapchainKHR( *device, swapChain, nullptr);
}
for ( auto& fence : waitFences ) {
vkDestroyFence( *device, fence, nullptr);
fence = VK_NULL_HANDLE;
}
presentCompleteSemaphore = VK_NULL_HANDLE;
renderCompleteSemaphore = VK_NULL_HANDLE;
swapChain = VK_NULL_HANDLE;
device = VK_NULL_HANDLE;
}

View File

@ -8,8 +8,8 @@
#include <ostream>
#include <fstream>
uint32_t ext::vulkan::width = 800;
uint32_t ext::vulkan::height = 600;
uint32_t ext::vulkan::width = 1280;
uint32_t ext::vulkan::height = 720;
bool ext::vulkan::validation = true;
ext::vulkan::Device ext::vulkan::device;
@ -17,15 +17,15 @@ ext::vulkan::Allocator ext::vulkan::allocator;
ext::vulkan::Swapchain ext::vulkan::swapchain;
std::mutex ext::vulkan::mutex;
bool ext::vulkan::resizedFramebuffer = false;
uint32_t ext::vulkan::currentBuffer = 600;
// std::vector<ext::vulkan::Graphic*> ext::vulkan::graphics;
bool ext::vulkan::rebuild = false;
uint32_t ext::vulkan::currentBuffer = 0;
std::vector<std::string> ext::vulkan::passes = { "BASE" };
//std::vector<ext::vulkan::Graphic*>* ext::vulkan::graphics = NULL;
std::vector<uf::Scene*> ext::vulkan::scenes;
std::string ext::vulkan::currentPass = "BASE";
std::vector<ext::vulkan::RenderMode*> ext::vulkan::renderModes;
std::vector<ext::vulkan::RenderMode*> ext::vulkan::renderModes = {
new ext::vulkan::BaseRenderMode,
};
VkResult ext::vulkan::CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) {
auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
@ -44,7 +44,8 @@ VKAPI_ATTR VkBool32 VKAPI_CALL ext::vulkan::debugCallback(
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData
) {
std::cerr << "[Validation Layer] " << pCallbackData->pMessage << std::endl;
if ( messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT ) return VK_FALSE;
uf::iostream << "[Validation Layer] " << pCallbackData->pMessage << "\n";
return VK_FALSE;
}
@ -52,7 +53,7 @@ VkShaderModule ext::vulkan::loadShader(const char *filename, VkDevice device) {
std::ifstream is(filename, std::ios::binary | std::ios::in | std::ios::ate);
if ( !is.is_open() ) {
std::cerr << "Error: Could not open shader file \"" << filename << "\"" << std::endl;
uf::iostream << "Error: Could not open shader file \"" << filename << "\"" << "\n";
return VK_NULL_HANDLE;
}
size_t size = is.tellg();
@ -155,13 +156,21 @@ ext::vulkan::RenderMode& ext::vulkan::addRenderMode( ext::vulkan::RenderMode* mo
renderModes.push_back(mode);
return *mode;
}
ext::vulkan::RenderMode& ext::vulkan::getRenderMode( const std::string& name ) {
RenderMode* target = renderModes[ renderModes.size()-1 ];
ext::vulkan::RenderMode& ext::vulkan::getRenderMode( const std::string& name, bool isName ) {
RenderMode* target = renderModes[0];
for ( auto& renderMode: renderModes ) {
if ( isName ) {
if ( renderMode->getName() == "" ) target = renderMode;
if ( renderMode->getName() == name ) {
target = renderMode;
break;
}
} else {
if ( renderMode->getType() == name ) {
target = renderMode;
break;
}
}
}
return *target;
}
@ -180,6 +189,7 @@ void ext::vulkan::initialize( uint8_t stage ) {
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
renderMode->initialize(device);
std::cout << "Initialized render mode `" << renderMode->name << "` (" << renderMode->getType() << ")" << std::endl;
}
/* resort */ {
/*
@ -222,7 +232,7 @@ void ext::vulkan::initialize( uint8_t stage ) {
if ( !mesh.generated ) return;
if ( graphic.initialized ) return;
graphic.initialize();
swapchain.rebuild = true;
ext::vulkan::rebuild = true;
};
for ( uf::Scene* scene : ext::vulkan::scenes ) {
if ( !scene ) continue;
@ -252,7 +262,7 @@ void ext::vulkan::tick() {
auto& graphics = *ext::vulkan::graphics;
for ( Graphic* graphic : graphics ) {
if ( !graphic->initialized ) {
swapchain.rebuild = true;
ext::vulkan::rebuild = true;
graphic->initialize();
}
}
@ -265,19 +275,19 @@ void ext::vulkan::tick() {
// if ( !graphic->process ) return;
if ( !mesh.generated ) return;
if ( graphic.initialized ) return;
swapchain.rebuild = true;
ext::vulkan::rebuild = true;
graphic.initialize();
};
for ( uf::Scene* scene : ext::vulkan::scenes ) {
if ( !scene ) continue;
scene->process(filter);
}
if ( swapchain.rebuild ) {
if ( ext::vulkan::rebuild ) {
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
renderMode->createCommandBuffers();
}
swapchain.rebuild = false;
ext::vulkan::rebuild = false;
}
// ext::vulkan::mutex.unlock();
}
@ -311,7 +321,7 @@ void ext::vulkan::render() {
}
// Handle resizes
if ( resizedFramebuffer ) resizedFramebuffer = false;
if ( ext::vulkan::rebuild ) ext::vulkan::rebuild = false;
}
void ext::vulkan::destroy() {
vkDeviceWaitIdle( device );
@ -320,21 +330,13 @@ void ext::vulkan::destroy() {
if ( !entity->hasComponent<uf::Mesh>() ) return;
uf::MeshBase& mesh = entity->getComponent<uf::Mesh>();
ext::vulkan::Graphic& graphic = mesh.graphic;
if ( !graphic.initialized ) return;
graphic.destroy();
};
for ( uf::Scene* scene : ext::vulkan::scenes ) {
if ( !scene ) continue;
scene->process(filter);
}
/*
if ( ext::vulkan::graphics ) {
auto& graphics = *ext::vulkan::graphics;
for ( Graphic* graphic : graphics ) {
graphic->destroy();
}
}
*/
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
renderMode->destroy();
@ -343,6 +345,7 @@ void ext::vulkan::destroy() {
}
vmaDestroyAllocator( allocator );
swapchain.destroy();
device.destroy();
}

View File

@ -110,8 +110,10 @@ void EXT_API ext::initialize() {
ext::vulkan::height = ::config["window"]["size"]["y"].asInt();
// setup render mode
if ( ::config["engine"]["render modes"]["deferred"].asBool() )
ext::vulkan::addRenderMode( new ext::vulkan::DeferredRenderMode, "" );
// ext::vulkan::addRenderMode( new ext::vulkan::RenderTargetRenderMode, "Gui" );
if ( ::config["engine"]["render modes"]["gui"].asBool() )
ext::vulkan::addRenderMode( new ext::vulkan::RenderTargetRenderMode, "Gui" );
ext::vulkan::initialize();
}
/* */ {

View File

@ -54,9 +54,9 @@ void ext::HousamoSprite::initialize() {
uf::Asset& assetLoader = world.getComponent<uf::Asset>();
this->addHook( "graphics:Assign.%UID%", [&](const std::string& event)->std::string{
uf::Mesh& mesh = this->getComponent<uf::Mesh>();
mesh.graphic.initialize();
mesh.graphic.autoAssign();
// uf::Mesh& mesh = this->getComponent<uf::Mesh>();
// mesh.graphic.initialize();
// mesh.graphic.autoAssign();
metadata["system"]["control"] = true;
metadata["system"]["loaded"] = true;
return "true";
@ -76,15 +76,17 @@ void ext::HousamoSprite::initialize() {
uf::Image image = *imagePointer;
uf::Mesh& mesh = this->getComponent<uf::Mesh>();
float scalex = 1.0f; //(640.0f / 1024.0f);
float scaley = 1.0f; //(904.0f / 1024.0f);
float scalex = 1.0f;
float scaley = 1.0f;
// float scaley = ((float) image.getDimensions().x / (float) image.getDimensions().y);
// float scalex = (640.0f / 1024.0f);
// float scaley = (904.0f / 1024.0f);
// float scalex = (image.getDimensions().x / 1024.0f);
// float scaley = (image.getDimensions().y / 1024.0f);
if ( metadata["orientation"] == "landscape" ) {
scalex = (904.0f / 1024.0f);
scaley = (640.0f / 1024.0f);
}
// std::cout << this->m_name ": " << metadata["orientation"] << std::endl;
mesh.vertices = {
{{-1*-0.5f, 0.0f, 0.0f}, {scalex*1.0f, scaley*0.0f}, { 0.0f, 0.0f, -1.0f } },
{{-1*0.5f, 0.0f, 0.0f}, {scalex*0.0f, scaley*0.0f}, { 0.0f, 0.0f, -1.0f } },

View File

@ -17,7 +17,7 @@
namespace {
bool SWIZZLE_OPTIMIZATION = false;
ext::TerrainVoxel::light_t AMBIENT_LIGHT = 0x1111; //{std::numeric_limits<ext::TerrainVoxel::light_t::type_t>::max(), std::numeric_limits<ext::TerrainVoxel::light_t::type_t>::max(), std::numeric_limits<ext::TerrainVoxel::light_t::type_t>::max()};
ext::TerrainVoxel::light_t AMBIENT_LIGHT = 0x6666; //{std::numeric_limits<ext::TerrainVoxel::light_t::type_t>::max(), std::numeric_limits<ext::TerrainVoxel::light_t::type_t>::max(), std::numeric_limits<ext::TerrainVoxel::light_t::type_t>::max()};
struct COLOR {
uint r : 4;
uint g : 4;
@ -204,6 +204,7 @@ void ext::TerrainGenerator::generate( ext::Region& region ){
// if ( (x) % (this->m_size.x / partitions) == 0 ) voxel = atlas.wall;
// if ( (z) % (this->m_size.z / partitions) == 0 ) voxel = atlas.wall;
/*
if ( (x + 1) % (this->m_size.x / partitions) == 0 ) voxel = atlas.wall;
if ( (z + 1) % (this->m_size.z / partitions) == 0 ) voxel = atlas.wall;
@ -211,8 +212,8 @@ void ext::TerrainGenerator::generate( ext::Region& region ){
if ( x % (this->m_size.x / partitions) >= 3 && x % (this->m_size.x / partitions) <= partitions - 4 ) voxel = 0;
if ( z % (this->m_size.z / partitions) >= 3 && z % (this->m_size.z / partitions) <= partitions - 4 ) voxel = 0;
}
*/
if ( y <= 1 ) voxel = atlas.floor; if ( y == this->m_size.y - 1 ) voxel = atlas.ceiling;
if ( uf::vector::sum(location) != 0 ) {
if ( e < 0.5 ) voxel = y == 0 ? atlas.lava : 0;
// if ( raw_noise[x][1][z] / maxValue < 0.2 || raw_noise[x][2][z] / maxValue > 0.8 ) voxel = atlas.stair;
@ -227,8 +228,8 @@ void ext::TerrainGenerator::generate( ext::Region& region ){
if ( LABYRINTH & ext::Maze::WEST ) if ( x == this->m_size.x - 1 ) voxel = atlas.wall;
if ( LABYRINTH & ext::Maze::NORTH ) if ( z == 0 ) voxel = atlas.wall;
if ( LABYRINTH & ext::Maze::SOUTH ) if ( z == this->m_size.z - 1 ) voxel = atlas.wall;
if ( LABYRINTH & ext::Maze::FLOOR ) if ( y == 0 ) voxel = atlas.floor;
if ( LABYRINTH & ext::Maze::CEIL ) if ( y == this->m_size.y - 1 ) voxel = atlas.ceiling;
// if ( LABYRINTH & ext::Maze::FLOOR ) if ( y == 0 ) voxel = atlas.floor;
// if ( LABYRINTH & ext::Maze::CEIL ) if ( y == this->m_size.y - 1 ) voxel = atlas.ceiling;
if ( light < AMBIENT_LIGHT ) light = AMBIENT_LIGHT;
@ -355,14 +356,14 @@ ext::TerrainVoxel::uid_t ext::TerrainGenerator::getVoxel( int x, int y, int z )
// if ( this->m_voxels.id.raw ) return this->m_voxels.id.raw[x][y][z];
if ( !this->m_voxels.id.raw.empty() ) {
std::size_t i = this->wrapPosition( x, y, z );
std::size_t i = this->wrapPosition( x, y, z, this->m_voxels.id.swizzle );
return this->m_voxels.id.raw[i];
}
std::size_t i = 0;
for ( auto& _ : this->m_voxels.id.rle ) {
for ( std::size_t __ = 0; __ < _.length; ++__ ) {
auto v = this->unwrapIndex( i++ );
auto v = this->unwrapIndex( i++, this->m_voxels.id.swizzle );
if ( v.x == x && v.y == y && v.z == z ) return _.value;
}
}
@ -440,14 +441,14 @@ ext::TerrainVoxel::light_t ext::TerrainGenerator::getLight( int x, int y, int z
/*
if ( !this->m_voxels.lighting.raw.empty() ) {
std::size_t i = this->wrapPosition( x, y, z );
std::size_t i = this->wrapPosition( x, y, z, this->m_voxels.lighting.swizzle );
return this->m_voxels.lighting.raw[i];
}
*/
std::size_t i = 0;
for ( auto& _ : this->m_voxels.lighting.rle ) {
for ( std::size_t __ = 0; __ < _.length; ++__ ) {
auto v = this->unwrapIndex( i++ );
auto v = this->unwrapIndex( i++, this->m_voxels.lighting.swizzle );
if ( v.x == x && v.y == y && v.z == z ) {
return _.value;
}
@ -474,9 +475,9 @@ pod::Vector3ui ext::TerrainGenerator::unwrapIndex( std::size_t i, Swizzle swizzl
this->m_size.y,
};
return {
i % this->m_size.x,
i / ( this->m_size.x * this->m_size.y ),
( i / this->m_size.x ) % this->m_size.y,
i % size.x,
i / ( size.x * size.y ),
( i / size.x ) % size.y,
};
break;
case Swizzle::ZXY:
@ -486,9 +487,9 @@ pod::Vector3ui ext::TerrainGenerator::unwrapIndex( std::size_t i, Swizzle swizzl
this->m_size.z,
};
return {
( i / this->m_size.x ) % this->m_size.y,
i % this->m_size.x,
i / ( this->m_size.x * this->m_size.y ),
( i / size.x ) % size.y,
i % size.x,
i / ( size.x * size.y ),
};
break;
case Swizzle::XYZ:
@ -499,9 +500,9 @@ pod::Vector3ui ext::TerrainGenerator::unwrapIndex( std::size_t i, Swizzle swizzl
this->m_size.x,
};
return {
( i / this->m_size.x ) % this->m_size.y,
i / ( this->m_size.x * this->m_size.y ),
i % this->m_size.x,
( i / size.x ) % size.y,
i / ( size.x * size.y ),
i % size.x,
};
break;
}
@ -565,7 +566,7 @@ void ext::TerrainGenerator::wrapVoxel() { if ( this->m_voxels.id.raw.empty() ) r
this->m_voxels.id.swizzle = ext::TerrainGenerator::DEFAULT_SWIZZLE;
for ( std::size_t i = 0; i < this->m_size.x * this->m_size.y * this->m_size.z; ++i ) {
auto position = this->unwrapIndex( i );
auto position = this->unwrapIndex( i, this->m_voxels.id.swizzle );
raw_id[position.x][position.y][position.z] = this->m_voxels.id.raw[i];
}
@ -622,7 +623,6 @@ void ext::TerrainGenerator::wrapVoxel() { if ( this->m_voxels.id.raw.empty() ) r
for ( uint x = 0; x < this->m_size.x; x++ )
buffer.push_back( raw_id[x][y][z] );
this->m_voxels.id.swizzle = Swizzle::YZX;
this->m_voxels.id.rle = uf::rle::encode( buffer );
}
}
@ -633,7 +633,7 @@ void ext::TerrainGenerator::wrapLight() { if ( this->m_voxels.lighting.raw.empty
this->m_voxels.lighting.swizzle = ext::TerrainGenerator::DEFAULT_SWIZZLE;
for ( std::size_t i = 0; i < this->m_size.x * this->m_size.y * this->m_size.z; ++i ) {
auto position = this->unwrapIndex( i );
auto position = this->unwrapIndex( i, this->m_voxels.lighting.swizzle );
raw_lighting[position.x][position.y][position.z] = this->m_voxels.lighting.raw[i];
}
@ -800,7 +800,7 @@ void ext::TerrainGenerator::setVoxel( int x, int y, int z, const ext::TerrainVox
if ( region ) region->getComponent<uf::Serializer>()["region"]["modified"] = true;
}
std::size_t i = this->wrapPosition(x, y, z);
std::size_t i = this->wrapPosition(x, y, z, this->m_voxels.id.swizzle);
this->m_voxels.id.raw[i] = voxel;
this->wrapVoxel();
@ -880,7 +880,7 @@ void ext::TerrainGenerator::setLight( int x, int y, int z, const ext::TerrainVox
if ( region ) region->getComponent<uf::Serializer>()["region"]["modified"] = true;
}
std::size_t i = this->wrapPosition(x, y, z);
std::size_t i = this->wrapPosition(x, y, z, this->m_voxels.lighting.swizzle);
// std::cout << "Set Voxel( " << x << ", " << y << ", " << z << ") ("<< i <<") to level " << light << std::endl;
this->m_voxels.lighting.raw[i] = light;
this->wrapLight();
@ -1211,8 +1211,7 @@ void ext::TerrainGenerator::light( const pod::Vector3i& location, const ext::Ter
void ext::TerrainGenerator::updateLight(){
// this->unwrapLight();
// set lights to original values
return;
/*
std::size_t i = 0;
std::cout << "Updating lights for " << this->m_location.x << ", " << this->m_location.y << ", " << this->m_location.z << std::endl;
for ( auto& _ : this->m_voxels.id.rle ) {
@ -1224,10 +1223,10 @@ void ext::TerrainGenerator::updateLight(){
}
}
//this->wrapLight();
*/
// set lights
/*
i = 0;
std::size_t i = 0;
for ( auto& _ : this->m_voxels.id.rle ) {
for ( std::size_t __ = 0; __ < _.length; ++__ ) {
ext::TerrainVoxel voxel = ext::TerrainVoxel::atlas( _.value );
@ -1236,7 +1235,6 @@ void ext::TerrainGenerator::updateLight(){
this->light(v.x, v.y, v.z, voxel.light() );
}
}
*/
// this->wrapLight();
// this->writeToFile();
}

View File

@ -126,7 +126,7 @@ void ext::Region::initialize() {
if ( first ) {
// shiro
{
if ( metadata["region"][""]["NPCs"].asBool() ) {
uf::Object* = new ext::HousamoSprite;
this->addChild(*);
uf::Serializer& pMetadata = ->getComponent<uf::Serializer>();
@ -137,7 +137,7 @@ void ext::Region::initialize() {
pTransform.position += transform.position + pod::Vector3f{ 2, 0, 0 };
}
// pong
{
if ( metadata["region"][""]["NPCs"].asBool() ) {
uf::Object* = new ext::HousamoSprite;
this->addChild(*);
uf::Serializer& pMetadata = ->getComponent<uf::Serializer>();
@ -194,7 +194,9 @@ void ext::Region::destroy() {
this->getComponent<ext::vulkan::RTGraphic>().destroy();
}
if ( this->hasComponent<ext::TerrainGenerator::mesh_t>() ) {
this->getComponent<ext::TerrainGenerator::mesh_t>().destroy();
auto& mesh = this->getComponent<ext::TerrainGenerator::mesh_t>();
mesh.graphic.destroy();
mesh.destroy();
}
uf::Object::destroy();
}

View File

@ -45,7 +45,9 @@ void ext::Terrain::destroy() {
this->getComponent<ext::vulkan::RTGraphic>().destroy();
}
if ( this->hasComponent<ext::TerrainGenerator::mesh_t>() ) {
this->getComponent<ext::TerrainGenerator::mesh_t>().destroy();
auto& mesh = this->getComponent<ext::TerrainGenerator::mesh_t>();
mesh.graphic.destroy();
mesh.destroy();
}
uf::Object::destroy();
}
@ -296,6 +298,10 @@ void ext::Terrain::tick() {
break;
}
}
{
uf::Serializer& rMetadata = kv->getComponent<uf::Serializer>();
if ( !rMetadata["region"]["rasterized"].asBool() ) degenerate = false;
}
if ( degenerate ) locations.push_back(location);
}
@ -495,6 +501,10 @@ void ext::Terrain::tick() {
break;
}
}
{
uf::Serializer& rMetadata = kv->getComponent<uf::Serializer>();
if ( !rMetadata["region"]["rasterized"].asBool() ) degenerate = false;
}
if ( degenerate ) locations.push_back(location);
}