Commit for 2020.07.24.7z
This commit is contained in:
parent
958b1697f6
commit
01ccc7fab4
@ -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" ) {
|
||||
|
@ -14,8 +14,8 @@ namespace ext {
|
||||
void* mapped = nullptr;
|
||||
|
||||
VkBufferUsageFlags usageFlags;
|
||||
|
||||
VkMemoryPropertyFlags memoryPropertyFlags;
|
||||
|
||||
VkMemoryAllocateInfo memAlloc;
|
||||
VkMemoryRequirements memReqs;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
31
engine/inc/uf/ext/vulkan/rendermode.h
Normal file
31
engine/inc/uf/ext/vulkan/rendermode.h
Normal 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();
|
||||
};
|
||||
}
|
||||
}
|
@ -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();
|
||||
};
|
||||
}
|
||||
}
|
@ -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();
|
||||
};
|
||||
}
|
||||
}
|
@ -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();
|
||||
};
|
||||
}
|
||||
}
|
@ -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();
|
||||
};
|
||||
}
|
||||
}
|
@ -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 );
|
||||
};
|
||||
}
|
||||
}
|
@ -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();
|
||||
};
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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 ) {
|
||||
|
@ -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 ) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
);
|
||||
|
||||
|
@ -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 = {};
|
||||
|
@ -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
|
||||
);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
);
|
||||
|
@ -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(¤tBuffer));
|
||||
VK_CHECK_RESULT(swapchain.acquireNextImage(¤tBuffer, 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;
|
||||
}
|
||||
}
|
@ -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(¤tBuffer));
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
@ -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]));
|
||||
}
|
||||
}
|
@ -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 );
|
@ -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]));
|
||||
}
|
||||
}
|
@ -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 );
|
||||
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
/* */ {
|
||||
|
@ -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 } },
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user