add transfer command

This commit is contained in:
ouczbs 2024-12-26 21:54:38 +08:00
parent 1bbddd1c7d
commit e68aef08d1
23 changed files with 223 additions and 131 deletions

View File

@ -6,13 +6,14 @@ namespace api {
public: public:
using UIWindow::UIWindow; using UIWindow::UIWindow;
void InitializeComponent() override; void InitializeComponent() override;
}; };
class EditorMainWindow : public EditorWindow { class EditorMainWindow : public EditorWindow {
public: public:
Noesis::Ptr<Noesis::IView> mView; Noesis::Ptr<Noesis::IView> mView;
public: public:
EditorMainWindow(); EditorMainWindow();
void DrawNoesisUI();
void Draw(FrameGraph& graph, RenderEditorContext& ctx) override; void Draw(FrameGraph& graph, RenderEditorContext& ctx) override;
}; };
} }

View File

@ -1,4 +1,4 @@
#include "render/renderapi.h" #include "render/render_api.h"
#include "render/render_module.h" #include "render/render_module.h"
namespace api { namespace api {
SINGLETON_DEFINE(RenderAPI) SINGLETON_DEFINE(RenderAPI)

View File

@ -36,14 +36,12 @@ namespace api {
virtual void CreateTexture(TextureDesc& desc) = 0; virtual void CreateTexture(TextureDesc& desc) = 0;
virtual ImageViewPtr CreateTextureView(TextureViewKey desc) = 0; virtual ImageViewPtr CreateTextureView(TextureViewKey desc) = 0;
virtual SamplerPtr CreateTextureSampler(TextureSampler sampler) = 0; virtual SamplerPtr CreateTextureSampler(TextureSampler sampler) = 0;
virtual void UpdateTexture(TextureDesc& texture, const TextureUpdateArgs& update, ResourceState state) = 0;
virtual void BeginFrame() = 0; virtual void BeginFrame() = 0;
virtual void EndFrame() = 0; virtual void EndFrame() = 0;
virtual void RenderView(FRenderView& view); virtual void RenderView(FRenderView& view);
using FnEnterRenderPass = void(*)(RenderPassNode*); using FnEnterRenderPass = void(*)(RenderPassNode*);
virtual void BeginRenderPass(RenderPassNode* node, FnEnterRenderPass callback) = 0; virtual void BeginRenderPass(RenderPassNode* node, FnEnterRenderPass callback) = 0;
virtual void EndRenderPass(RenderPassNode* node) = 0; virtual void EndRenderPass(RenderPassNode* node) = 0;
virtual void ExecuteResourceBarriers(const ResourceBarrierDesc& desc) = 0;
void Render(); void Render();
}; };
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#define PREALLOCATED_DYNAMIC_BUFFER_PAGES 2 #define PREALLOCATED_DYNAMIC_BUFFER_PAGES 2
#include "renderapi.h" #include "render_api.h"
namespace api { namespace api {
struct DynamicBufferDesc { struct DynamicBufferDesc {
uint32_t size; uint32_t size;

View File

@ -6,6 +6,12 @@ namespace api {
struct FRenderView { struct FRenderView {
RenderContext* context; RenderContext* context;
}; };
enum class RenderPassState : uint8_t {
Default,
BeginRecord,
BeginRender,
Present,
};
struct RenderContext { struct RenderContext {
pmr::vector<FRenderView> views; pmr::vector<FRenderView> views;
TextureDesc surface; TextureDesc surface;
@ -13,6 +19,7 @@ namespace api {
uint32_t frame{ 0 }; uint32_t frame{ 0 };
uint32_t presentFrame{ 0 }; uint32_t presentFrame{ 0 };
uint32_t frameNumber{ 0 }; uint32_t frameNumber{ 0 };
RenderPassState renderPassState{ RenderPassState::Default };
virtual void SetViewport(float x, float y, float width, float height, float min_depth, float max_depth) = 0; virtual void SetViewport(float x, float y, float width, float height, float min_depth, float max_depth) = 0;
virtual void SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0; virtual void SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0;
virtual void BindIndexBuffer(BufferDesc desc, uint32_t index_stride) = 0; virtual void BindIndexBuffer(BufferDesc desc, uint32_t index_stride) = 0;
@ -20,5 +27,7 @@ namespace api {
virtual void BindVertexBuffers(uint32_t buffer_count, const BufferDesc* buffers, const uint32_t* offsets) = 0; virtual void BindVertexBuffers(uint32_t buffer_count, const BufferDesc* buffers, const uint32_t* offsets) = 0;
virtual void DrawIndexed(uint32_t index_count, uint32_t first_index, uint32_t first_vertex) = 0; virtual void DrawIndexed(uint32_t index_count, uint32_t first_index, uint32_t first_vertex) = 0;
virtual void ExecuteSurfaceBarriers(const ResourceBarrierDesc& desc) = 0; virtual void ExecuteSurfaceBarriers(const ResourceBarrierDesc& desc) = 0;
virtual void ExecuteResourceBarriers(const ResourceBarrierDesc& desc) = 0;
virtual void UpdateTexture(TextureDesc& texture, const TextureUpdateArgs& update, ResourceState state) = 0;
}; };
} }

View File

@ -34,12 +34,14 @@ namespace api {
LastOutput = 0x04, LastOutput = 0x04,
}; };
enum class BufferUsage : uint8_t { enum class BufferUsage : uint8_t {
STATIC = 0x01, //!< content modified once, used many times None = 0,
DYNAMIC = 0x02, //!< content modified frequently, used many times STATIC, //!< content modified once, used many times
VERTEX = 0x04, DYNAMIC, //!< content modified frequently, used many times
UNIFORM = 0x08, VERTEX,
SHADER_STORAGE = 0x10, INDEX,
TRANSFER_SRC = 0x20, UNIFORM,
SHADER_STORAGE,
TRANSFER_SRC,
}; };
/* /*
@ -343,7 +345,6 @@ namespace api {
return barrier; return barrier;
} }
struct ResourceBarrierDesc { struct ResourceBarrierDesc {
RenderPassType type;
const BufferBarrier* pBufferBarriers; const BufferBarrier* pBufferBarriers;
uint32_t bufferBarriersCount; uint32_t bufferBarriersCount;
const TextureBarrier* pTextureBarriers; const TextureBarrier* pTextureBarriers;
@ -369,6 +370,7 @@ namespace api {
uint32_t y; uint32_t y;
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
uint32_t mipLevel;
const void* data; const void* data;
}; };
} }

View File

@ -1,5 +1,5 @@
#include "render/graph/frame_graph.h" #include "render/graph/frame_graph.h"
#include "render/renderapi.h" #include "render/render_api.h"
#include <stack> #include <stack>
#include <unordered_set> #include <unordered_set>
#include <algorithm> #include <algorithm>
@ -172,7 +172,6 @@ namespace api {
barrier.mDstState = ResourceState::PRESENT; barrier.mDstState = ResourceState::PRESENT;
barrier.mTexture = surface; barrier.mTexture = surface;
ResourceBarrierDesc desc{}; ResourceBarrierDesc desc{};
desc.type = RenderPassType::Present;
desc.textureBarriersCount = 1; desc.textureBarriersCount = 1;
desc.pTextureBarriers = &barrier; desc.pTextureBarriers = &barrier;
view.context->ExecuteSurfaceBarriers(desc); view.context->ExecuteSurfaceBarriers(desc);
@ -211,12 +210,11 @@ namespace api {
return; return;
} }
ResourceBarrierDesc desc{}; ResourceBarrierDesc desc{};
desc.type = type;
desc.bufferBarriersCount = bufferBarrier.size(); desc.bufferBarriersCount = bufferBarrier.size();
desc.pBufferBarriers = bufferBarrier.data(); desc.pBufferBarriers = bufferBarrier.data();
desc.textureBarriersCount = textureBarrier.size(); desc.textureBarriersCount = textureBarrier.size();
desc.pTextureBarriers = textureBarrier.data(); desc.pTextureBarriers = textureBarrier.data();
RenderAPI::Ptr()->ExecuteResourceBarriers(desc); RenderAPI::Ptr()->context.ExecuteResourceBarriers(desc);
} }
void FrameGraph::TransitionState(TextureDesc& desc, ResourceState state) void FrameGraph::TransitionState(TextureDesc& desc, ResourceState state)
{ {

View File

@ -1,7 +1,7 @@
#include "render/pass/demo_pass.h" #include "render/pass/demo_pass.h"
#include "render/asset/shader.h" #include "render/asset/shader.h"
#include "render/asset/material.h" #include "render/asset/material.h"
#include "render/renderapi.h" #include "render/render_api.h"
#include "asset/resource_system.h" #include "asset/resource_system.h"
#include "render/asset/vertex.h" #include "render/asset/vertex.h"
#include "render/asset/mesh.h" #include "render/asset/mesh.h"

View File

@ -1,6 +1,6 @@
#include "render/tool/glsl_to_spirv.h" #include "render/tool/glsl_to_spirv.h"
#include "render/asset/ubo.h" #include "render/asset/ubo.h"
#include "render/renderapi.h" #include "render/render_api.h"
#include "zlog.h" #include "zlog.h"
#include <shaderc/shaderc.hpp> #include <shaderc/shaderc.hpp>
#include <spirv_cross/spirv_reflect.hpp> #include <spirv_cross/spirv_reflect.hpp>

View File

@ -30,7 +30,4 @@ namespace api{
bool isInverted = false; bool isInverted = false;
bool hasAlpha = false; bool hasAlpha = false;
}; };
static Noesis::Ptr<Noesis::Texture> CreateUITexture(TextureDesc& desc) {
return Noesis::MakePtr<UITexture>(desc);
}
} }

View File

@ -1,10 +1,38 @@
#include "ui/ui_render_device.h" #include "ui/ui_render_device.h"
#include "ui/ui_module.h" #include "ui/ui_module.h"
#include "ui_render_device_help.inl" #include "ui_render_device_help.inl"
#include "render/render_buffer.h"
#define CBUFFER_SIZE 16 * 1024
namespace api { namespace api {
class UIRenderDeviceImpl {
public:
RenderAPI* mApi;
DynamicBuffer mVertices;
DynamicBuffer mIndices;
DynamicBuffer mConstants[4];
Noesis::DeviceCaps mCaps;
UIRenderDeviceImpl(RenderAPI* api) : mApi(api){
ResourceMemoryUsage memoryUsage = ResourceMemoryUsage::HOST_VISIBLE |
ResourceMemoryUsage::HOST_COHERENT | ResourceMemoryUsage::GPU_ONLY;
mVertices.InitBuffer(DYNAMIC_VB_SIZE, BufferUsage::VERTEX, memoryUsage);
mIndices.InitBuffer(DYNAMIC_IB_SIZE, BufferUsage::INDEX, memoryUsage);
mConstants[0].InitBuffer(CBUFFER_SIZE, BufferUsage::UNIFORM, memoryUsage);
mConstants[1].InitBuffer(CBUFFER_SIZE, BufferUsage::UNIFORM, memoryUsage);
mConstants[2].InitBuffer(CBUFFER_SIZE, BufferUsage::UNIFORM, memoryUsage);
mConstants[3].InitBuffer(CBUFFER_SIZE, BufferUsage::UNIFORM, memoryUsage);
}
Noesis::Ptr<Noesis::Texture> CreateTexture(TextureDesc& desc) {
mApi->CreateTexture(desc);
return Noesis::MakePtr<UITexture>(desc);
}
RenderContext& Context() {
return mApi->context;
}
};
SINGLETON_DEFINE(UIRenderDevice) SINGLETON_DEFINE(UIRenderDevice)
UIRenderDevice::UIRenderDevice(RenderAPI* api) : mApi(api) UIRenderDevice::UIRenderDevice(RenderAPI* api)
{ {
mImpl = new (GlobalPool()) UIRenderDeviceImpl(api);
SINGLETON_PTR(); SINGLETON_PTR();
} }
UIRenderDevice::~UIRenderDevice() UIRenderDevice::~UIRenderDevice()
@ -16,7 +44,7 @@ namespace api {
} }
const Noesis::DeviceCaps& UIRenderDevice::GetCaps() const const Noesis::DeviceCaps& UIRenderDevice::GetCaps() const
{ {
return mCaps; return mImpl->mCaps;
} }
Noesis::Ptr<Noesis::RenderTarget> UIRenderDevice::CreateRenderTarget(const char* label, uint32_t width, uint32_t height, uint32_t sampleCount, bool needsStencil) Noesis::Ptr<Noesis::RenderTarget> UIRenderDevice::CreateRenderTarget(const char* label, uint32_t width, uint32_t height, uint32_t sampleCount, bool needsStencil)
{ {
@ -30,21 +58,23 @@ namespace api {
{ {
TextureDesc desc{}; TextureDesc desc{};
desc.id = -1; desc.id = -1;
desc.format = VKFormat(format, mCaps.linearRendering); desc.format = VKFormat(format, mImpl->mCaps.linearRendering);
desc.width = width; desc.width = width;
desc.height = height; desc.height = height;
desc.mipLevel = numLevels; desc.mipLevel = numLevels;
desc.sampleCount = SAMPLE_COUNT_1; desc.sampleCount = SAMPLE_COUNT_1;
desc.usage = TextureUsage::SAMPLEABLE | TextureUsage::BLIT_DST; desc.usage = TextureUsage::SAMPLEABLE | TextureUsage::BLIT_DST;
desc.state = ResourceState::UNDEFINED; desc.state = ResourceState::UNDEFINED;
mApi->CreateTexture(desc); desc.dimension = TextureDimension::TEX_2D;
return CreateUITexture(desc); desc.depth = 1;
desc.arraySize = 1;
return mImpl->CreateTexture(desc);
} }
void UIRenderDevice::UpdateTexture(Noesis::Texture* texture, uint32_t level, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data) void UIRenderDevice::UpdateTexture(Noesis::Texture* texture, uint32_t level, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data)
{ {
UITexture* uiTex = (UITexture*)texture; UITexture* uiTex = (UITexture*)texture;
TextureUpdateArgs args{.x = x, .y = y, .width = width,.height = height, .data = data}; TextureUpdateArgs args{.x = x, .y = y, .width = width,.height = height, .mipLevel = level, .data = data};
mApi->UpdateTexture(uiTex->desc, args, ResourceState::TRANSFER_DST); mImpl->Context().UpdateTexture(uiTex->desc, args, ResourceState::TRANSFER_DST);
} }
void UIRenderDevice::BeginOffscreenRender() void UIRenderDevice::BeginOffscreenRender()
{ {
@ -104,33 +134,19 @@ namespace api {
} }
void* UIRenderDevice::MapVertices(uint32_t bytes) void* UIRenderDevice::MapVertices(uint32_t bytes)
{ {
int b = 10000; auto& ctx = mImpl->Context();
for (int a = 1; a < b; a++) { return mImpl->mVertices.MapBuffer(bytes, ctx.frameNumber, ctx.frameNumber - ctx.frameCount);
b--;
}
return nullptr;
} }
void UIRenderDevice::UnmapVertices() void UIRenderDevice::UnmapVertices()
{ {
int b = 10000;
for (int a = 1; a < b; a++) {
b--;
}
} }
void* UIRenderDevice::MapIndices(uint32_t bytes) void* UIRenderDevice::MapIndices(uint32_t bytes)
{ {
int b = 10000; auto& ctx = mImpl->Context();
for (int a = 1; a < b; a++) { return mImpl->mIndices.MapBuffer(bytes, ctx.frameNumber, ctx.frameNumber - ctx.frameCount);
b--;
}
return nullptr;
} }
void UIRenderDevice::UnmapIndices() void UIRenderDevice::UnmapIndices()
{ {
int b = 10000;
for (int a = 1; a < b; a++) {
b--;
}
} }
void UIRenderDevice::DrawBatch(const Noesis::Batch& batch) void UIRenderDevice::DrawBatch(const Noesis::Batch& batch)
{ {

View File

@ -1,15 +1,18 @@
#pragma once #pragma once
#include "render/renderapi.h" #include "render/render_api.h"
#include <NsRender/RenderDevice.h> #include <NsRender/RenderDevice.h>
namespace api { namespace api {
class UIRenderDeviceImpl;
class UI_API UIRenderDevice final : public Noesis::RenderDevice { class UI_API UIRenderDevice final : public Noesis::RenderDevice {
private: private:
RenderAPI* mApi; UIRenderDeviceImpl* mImpl;
Noesis::DeviceCaps mCaps;
SINGLETON_IMPL(UIRenderDevice) SINGLETON_IMPL(UIRenderDevice)
public: public:
UIRenderDevice(RenderAPI* api); UIRenderDevice(RenderAPI* api);
~UIRenderDevice(); ~UIRenderDevice();
static void* operator new(size_t size) {
return GlobalPool()->allocate(size, 8);
}
private: private:
/// From RenderDevice /// From RenderDevice
//@{ //@{

View File

@ -42,10 +42,10 @@ namespace vkn {
VkImage* image; VkImage* image;
}; };
struct ImageUpdator { struct ImageUpdator {
TextureUpdateArgs args;
VkCommandBuffer command;
VkImage image; VkImage image;
uint32_t size; uint32_t size;
uint32_t mipLevel;
TextureUpdateArgs args;
}; };
struct SyncTransferCommand { struct SyncTransferCommand {
uint32_t frameNumber; uint32_t frameNumber;
@ -85,6 +85,6 @@ namespace vkn {
void UpdateImage(ImageUpdator& elem, TransferBufferType type = TransferBufferType::Graphics); void UpdateImage(ImageUpdator& elem, TransferBufferType type = TransferBufferType::Graphics);
bool BeginDynamicCommand(DynamicBufferPool*& poolRef, CommandBuffer& cmd, bool isTransfer); bool BeginDynamicCommand(DynamicBufferPool*& poolRef, CommandBuffer& cmd, bool isTransfer);
void EndDynamicCommand(DynamicBufferPool* poolRef, CommandBuffer& cmd, bool isTransfer); void EndDynamicCommand(DynamicBufferPool* poolRef, CommandBuffer cmd, bool isTransfer);
}; };
}; };

View File

@ -7,6 +7,18 @@
#include "render/render_type.h" #include "render/render_type.h"
#include "render/type.h" #include "render/type.h"
#define Z_RENDER_DEBUG 1 #define Z_RENDER_DEBUG 1
#define VKN_MACRO_BEGIN \
__pragma(warning(push)) \
__pragma(warning(disable:4127)) \
do {
#define VKN_MACRO_END \
} while(false) \
__pragma(warning(pop))
#define V(exp) \
VKN_MACRO_BEGIN \
VkResult err_ = (exp); \
assert(err_ == VK_SUCCESS); \
VKN_MACRO_END
namespace vkn { namespace vkn {
using pmr::Name; using pmr::Name;
using pmr::table; using pmr::table;

View File

@ -41,13 +41,11 @@ namespace vkn {
void CreateTexture(TextureDesc& desc)override; void CreateTexture(TextureDesc& desc)override;
ImageViewPtr CreateTextureView(TextureViewKey desc)override; ImageViewPtr CreateTextureView(TextureViewKey desc)override;
SamplerPtr CreateTextureSampler(TextureSampler sampler) override; SamplerPtr CreateTextureSampler(TextureSampler sampler) override;
void UpdateTexture(TextureDesc& texture, const TextureUpdateArgs& update, ResourceState state) override;
void BeginFrame()override; void BeginFrame()override;
void EndFrame()override; void EndFrame()override;
void BeginRenderPass(RenderPassNode* node, FnEnterRenderPass callback) override; void BeginRenderPass(RenderPassNode* node, FnEnterRenderPass callback) override;
void EndRenderPass(RenderPassNode* node) override; void EndRenderPass(RenderPassNode* node) override;
void ExecuteResourceBarriers(const ResourceBarrierDesc& desc) override;
VkPipeline GetPipeline() { return nullptr; }; VkPipeline GetPipeline() { return nullptr; };
RenderPassInfo* GetRenderPassInfo(Name name, size_t hash); RenderPassInfo* GetRenderPassInfo(Name name, size_t hash);

View File

@ -1,13 +1,15 @@
#pragma once #pragma once
#include "type.h" #include "type.h"
#include "render/renderapi.h" #include "render/render_api.h"
namespace vkn { namespace vkn {
using api::BufferDesc; using api::BufferDesc;
using api::RenderPassState;
struct VulkanContext : public api::RenderContext { struct VulkanContext : public api::RenderContext {
VkFence surfaceFence; VkFence surfaceFence;
VkSemaphore surfaceSemaphore; VkSemaphore surfaceSemaphore;
VkSemaphore presentSemaphore; VkSemaphore presentSemaphore;
VkSemaphore graphSemaphore; VkSemaphore graphSemaphore;
VkCommandBuffer transferCommand;
VkCommandBuffer surfaceCommand; VkCommandBuffer surfaceCommand;
VkCommandBuffer command; VkCommandBuffer command;
void SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; void SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override;
@ -17,9 +19,13 @@ namespace vkn {
void BindVertexBuffers(uint32_t buffer_count, const BufferDesc* descs, const uint32_t* offsets)override; void BindVertexBuffers(uint32_t buffer_count, const BufferDesc* descs, const uint32_t* offsets)override;
void DrawIndexed(uint32_t index_count, uint32_t first_index, uint32_t first_vertex) override; void DrawIndexed(uint32_t index_count, uint32_t first_index, uint32_t first_vertex) override;
void ExecuteSurfaceBarriers(const ResourceBarrierDesc& desc) override; void ExecuteSurfaceBarriers(const ResourceBarrierDesc& desc) override;
void ExecuteResourceBarriers(const ResourceBarrierDesc& desc) override;
void UpdateTexture(TextureDesc& texture, const TextureUpdateArgs& update, ResourceState state) override;
void ClearSurface(VkClearColorValue clearValue); void ClearSurface(VkClearColorValue clearValue);
void BeginRecord(VkCommandBufferUsageFlags flag); void BeginRecord(VkCommandBuffer cmd, VkCommandBufferUsageFlags flag);
void EndRecord(VkQueue queue); void EndRecord(VkQueue queue);
void FlushCommand();
VkCommandBuffer GetTransferCommand();
}; };
} }

View File

@ -32,6 +32,7 @@ namespace vkn {
VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args); VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args);
void Aquire(VulkanContext& ctx); void Aquire(VulkanContext& ctx);
void Present(VulkanContext& ctx); void Present(VulkanContext& ctx);
VkCommandBuffer GetTransferCommand(uint32_t frame) { return mCommands[frame + mFrames]; };
}; };
class VULKAN_API VulkanWindow : public api::Window { class VULKAN_API VulkanWindow : public api::Window {
private: private:
@ -49,6 +50,7 @@ namespace vkn {
} }
void Aquire(VulkanContext& ctx) { mSwapchain->Aquire(ctx); }; void Aquire(VulkanContext& ctx) { mSwapchain->Aquire(ctx); };
void Present(VulkanContext& ctx) { mSwapchain->Present(ctx); }; void Present(VulkanContext& ctx) { mSwapchain->Present(ctx); };
VkCommandBuffer GetTransferCommand(uint32_t frame) { return mSwapchain->GetTransferCommand(frame); };
VulkanSwapchain* Swapchain() { VulkanSwapchain* Swapchain() {
return mSwapchain; return mSwapchain;
} }

View File

@ -148,13 +148,14 @@ namespace vkn {
allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
VmaAllocation allocation; VmaAllocation allocation;
VkResult result = vmaCreateImage(vmaAllocator, &elem.imageInfo, &allocCreateInfo, elem.image, &allocation, nullptr); V(vmaCreateImage(vmaAllocator, &elem.imageInfo, &allocCreateInfo, elem.image, &allocation, nullptr));
zlog::info("CreateImage {:#x} {} {}::{}",(uintptr_t)*elem.image, (uint32_t)elem.imageInfo.format, elem.imageInfo.extent.width, elem.imageInfo.extent.height);
} }
void BufferWorker::UpdateImage(ImageUpdator& elem, TransferBufferType type) void BufferWorker::UpdateImage(ImageUpdator& elem, TransferBufferType type)
{ {
bool isTransfer = type == TransferBufferType::Transfer; bool isTransfer = type == TransferBufferType::Transfer;
DynamicBufferPool* pPoolRef; DynamicBufferPool* pPoolRef;
CommandBuffer command; CommandBuffer command = elem.command;
if (!BeginDynamicCommand(pPoolRef, command, isTransfer)) { if (!BeginDynamicCommand(pPoolRef, command, isTransfer)) {
Invoke(elem); Invoke(elem);
return; return;
@ -162,25 +163,29 @@ namespace vkn {
TextureUpdateArgs args = elem.args; TextureUpdateArgs args = elem.args;
// 将数据复制到 Staging Buffer // 将数据复制到 Staging Buffer
DynamicBuffer* uploadBuffer = pPoolRef->FindUploadBuffer(elem.size, mFrameNumber + 1, args.data); DynamicBuffer* uploadBuffer = pPoolRef->FindUploadBuffer(elem.size, mFrameNumber + 1, args.data);
zlog::info("update {:#x} {}::{} {}::{}", (uintptr_t)elem.image,args.x,args.y ,args.width, args.height);
VkBufferImageCopy region{}; VkBufferImageCopy region{};
region.imageOffset.x = args.x; region.imageOffset.x = args.x;
region.imageOffset.y = args.y; region.imageOffset.y = args.y;
region.imageExtent.width = args.width; region.imageExtent.width = args.width;
region.imageExtent.height = args.height; region.imageExtent.height = args.height;
region.imageExtent.depth = 1; region.imageExtent.depth = 1;
region.imageSubresource.mipLevel = elem.mipLevel; region.imageSubresource.mipLevel = args.mipLevel;
region.bufferOffset = uploadBuffer->drawPos; region.bufferOffset = uploadBuffer->drawPos;
region.imageSubresource.layerCount = 1; region.imageSubresource.layerCount = 1;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
vkCmdCopyBufferToImage(command.Ptr(), (VkBuffer)uploadBuffer->currentPage->pBuffer, elem.image, vkCmdCopyBufferToImage(command.Ptr(), (VkBuffer)uploadBuffer->currentPage->pBuffer, elem.image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region); VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
EndDynamicCommand(pPoolRef, command, isTransfer); if(!elem.command)
EndDynamicCommand(pPoolRef, command, isTransfer);
} }
bool BufferWorker::BeginDynamicCommand(DynamicBufferPool*& pPoolRef, CommandBuffer& command, bool isTransfer) bool BufferWorker::BeginDynamicCommand(DynamicBufferPool*& pPoolRef, CommandBuffer& command, bool isTransfer)
{ {
pPoolRef = isTransfer ? &mTransferBuffer : &mGraphicsBuffer; pPoolRef = isTransfer ? &mTransferBuffer : &mGraphicsBuffer;
if (command.Ptr()) {
return true;
}
if (pPoolRef->commandIndex >= MAX_TRANSFER_SYNC_FENCES) { if (pPoolRef->commandIndex >= MAX_TRANSFER_SYNC_FENCES) {
return false; return false;
} }
@ -188,7 +193,7 @@ namespace vkn {
command.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); command.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
return true; return true;
} }
void BufferWorker::EndDynamicCommand(DynamicBufferPool* pPoolRef, CommandBuffer& command, bool isTransfer) void BufferWorker::EndDynamicCommand(DynamicBufferPool* pPoolRef, CommandBuffer command, bool isTransfer)
{ {
command.EndRecord(); command.EndRecord();
pPoolRef->commandIndex++; pPoolRef->commandIndex++;

View File

@ -340,31 +340,6 @@ namespace vkn {
vkCreateSampler(backend.GetDevice().Ptr(), &samplerInfo, nullptr, &sampler); vkCreateSampler(backend.GetDevice().Ptr(), &samplerInfo, nullptr, &sampler);
return sampler; return sampler;
} }
void VulkanAPI::UpdateTexture(TextureDesc& texture, const TextureUpdateArgs& update, ResourceState state)
{
if (!texture.id) {
graph.AcquireTexture(texture);
}
if (texture.state != state) {
TextureBarrier barrier{};
barrier.mSrcState = texture.state;
barrier.mDstState = state;
barrier.mTexture = texture;
ResourceBarrierDesc desc{};
desc.pTextureBarriers = &barrier;
desc.textureBarriersCount = 1;
ExecuteResourceBarriers(desc);
}
VulkanContext& ctx = *(VulkanContext*)&context;
uint32_t texelBytes = texture.format == TinyImageFormat_R8_UNORM ? 1 : 4;
uint32_t size = update.width * update.height * texelBytes;
ImageUpdator updator{};
updator.args = update;
updator.size = size;
updator.mipLevel = texture.mipLevel;
updator.image = (VkImage)texture.image;
Backend::TransferWorker->UpdateImage(updator);
}
void VulkanAPI::BeginFrame() void VulkanAPI::BeginFrame()
{ {
VulkanContext& ctx = *(VulkanContext*)&context; VulkanContext& ctx = *(VulkanContext*)&context;
@ -375,28 +350,10 @@ namespace vkn {
void VulkanAPI::EndFrame() void VulkanAPI::EndFrame()
{ {
VulkanContext& ctx = *(VulkanContext*)&context; VulkanContext& ctx = *(VulkanContext*)&context;
ctx.FlushCommand();
window.Present(ctx); window.Present(ctx);
Backend::TransferWorker->TrySyncTransfer(ctx); Backend::TransferWorker->TrySyncTransfer(ctx);
} }
void VulkanAPI::ExecuteResourceBarriers(const ResourceBarrierDesc& desc) {
VulkanContext& ctx = *(VulkanContext*)&context;
pmr::vector<VkBufferMemoryBarrier> bufferBarriers{ FramePool() };
bufferBarriers.reserve(desc.bufferBarriersCount);
pmr::vector<VkImageMemoryBarrier> imageBarriers{ FramePool() };
imageBarriers.reserve(desc.textureBarriersCount);
VkPipelineStageFlags srcStageMask = 0, dstStageMask = 0;
for (uint32_t i = 0; i < desc.textureBarriersCount; i++)
{
auto& barrier = desc.pTextureBarriers[i];
auto desc = vkApiGetTextureTransition(srcStageMask, dstStageMask, barrier);
imageBarriers.push_back(desc);
}
if (dstStageMask == 0) {
dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
}
VkCommandBuffer command = desc.type == RenderPassType::Present ? ctx.surfaceCommand : ctx.command;
vkCmdPipelineBarrier(command, srcStageMask, dstStageMask, 0, 0, NULL, 0, NULL, imageBarriers.size(), imageBarriers.data());
}
void VulkanAPI::BeginRenderPass(RenderPassNode* node, FnEnterRenderPass callback) void VulkanAPI::BeginRenderPass(RenderPassNode* node, FnEnterRenderPass callback)
{ {
RenderPassKey config{}; RenderPassKey config{};
@ -481,8 +438,10 @@ namespace vkn {
CommandBuffer cmd = passInfo->commands[context.frame]; CommandBuffer cmd = passInfo->commands[context.frame];
ctx.command = cmd.Ptr(); ctx.command = cmd.Ptr();
cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
ctx.renderPassState = RenderPassState::BeginRecord;
if(callback) callback(node); if(callback) callback(node);
vkCmdBeginRenderPass(cmd.Ptr(), &beginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(cmd.Ptr(), &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
ctx.renderPassState = RenderPassState::BeginRender;
if (clearSurfaceIndex != -1)ctx.ClearSurface(clearValues[clearSurfaceIndex].color); if (clearSurfaceIndex != -1)ctx.ClearSurface(clearValues[clearSurfaceIndex].color);
} }
void VulkanAPI::EndRenderPass(RenderPassNode* node) void VulkanAPI::EndRenderPass(RenderPassNode* node)
@ -492,6 +451,7 @@ namespace vkn {
CommandBuffer cmd = passInfo->commands[context.frame]; CommandBuffer cmd = passInfo->commands[context.frame];
vkCmdEndRenderPass(cmd.Ptr()); vkCmdEndRenderPass(cmd.Ptr());
cmd.EndRecord(); cmd.EndRecord();
ctx.renderPassState = RenderPassState::Default;
VkSemaphore waitSemaphores[8]; VkSemaphore waitSemaphores[8];
VkPipelineStageFlags waitDstStageMasks[8]; VkPipelineStageFlags waitDstStageMasks[8];
uint32_t semaphoreCount = 0; uint32_t semaphoreCount = 0;

View File

@ -186,8 +186,12 @@ namespace vkn {
usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
if (any(usage & TextureUsage::DEPTH_ATTACHMENT)) if (any(usage & TextureUsage::DEPTH_ATTACHMENT))
usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
if(any(usage & TextureUsage::SAMPLEABLE)) if (any(usage & TextureUsage::SAMPLEABLE))
usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT; usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
if (any(usage & TextureUsage::BLIT_DST))
usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
if (any(usage & TextureUsage::BLIT_SRC))
usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
return usageFlags; return usageFlags;
} }
VkImageViewType vkApiGetImageViewType(TextureDimension dimension, uint32_t arraySize) VkImageViewType vkApiGetImageViewType(TextureDimension dimension, uint32_t arraySize)
@ -369,19 +373,21 @@ namespace vkn {
} }
VkBufferUsageFlagBits vkApiGetBufferUsage(BufferUsage usage) VkBufferUsageFlagBits vkApiGetBufferUsage(BufferUsage usage)
{ {
if (any(usage & BufferUsage::VERTEX)) { switch (usage)
{
case api::BufferUsage::VERTEX:
return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
} case api::BufferUsage::INDEX:
if (any(usage & BufferUsage::UNIFORM)) { return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
case api::BufferUsage::UNIFORM:
return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
} case api::BufferUsage::SHADER_STORAGE:
if (any(usage & BufferUsage::SHADER_STORAGE)) {
return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
} case api::BufferUsage::TRANSFER_SRC:
if (any(usage & BufferUsage::TRANSFER_SRC)) {
return VK_BUFFER_USAGE_TRANSFER_SRC_BIT; return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
default:
return {};
} }
return {};
} }
VkMemoryPropertyFlags vkApiGetMemoryFlags(ResourceMemoryUsage usageFlags) { VkMemoryPropertyFlags vkApiGetMemoryFlags(ResourceMemoryUsage usageFlags) {
VkMemoryPropertyFlags flags = 0; VkMemoryPropertyFlags flags = 0;

View File

@ -1,6 +1,9 @@
#include "vkn/backend.h" #include "vkn/backend.h"
#include "vkn/vulkan_api.h" #include "vkn/vulkan_api.h"
#include "vkn/thread/command_worker.h" #include "vkn/thread/command_worker.h"
#include "vkn/vulkan_api_help.h"
#include "vkn/thread/buffer_worker.h"
#include "vkn/vulkan_window.h"
#include "zlog.h" #include "zlog.h"
namespace vkn { namespace vkn {
void VulkanContext::SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height) void VulkanContext::SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
@ -50,12 +53,6 @@ namespace vkn {
{ {
vkCmdDrawIndexed(command, index_count, 1, first_index, first_vertex, 0); vkCmdDrawIndexed(command, index_count, 1, first_index, first_vertex, 0);
} }
void VulkanContext::ExecuteSurfaceBarriers(const ResourceBarrierDesc& desc)
{
BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
VulkanAPI::Ptr()->ExecuteResourceBarriers(desc);
EndRecord(Backend::RenderWorker->GetQueue().Ptr());
}
void VulkanContext::ClearSurface(VkClearColorValue clearValue) void VulkanContext::ClearSurface(VkClearColorValue clearValue)
{ {
// 条件满足时,手动清除附件 // 条件满足时,手动清除附件
@ -73,14 +70,14 @@ namespace vkn {
// 使用 vkCmdClearAttachments 清除颜色附件 // 使用 vkCmdClearAttachments 清除颜色附件
vkCmdClearAttachments(command, 1, &clearAttachment, 1, &clearRect); vkCmdClearAttachments(command, 1, &clearAttachment, 1, &clearRect);
} }
void VulkanContext::BeginRecord(VkCommandBufferUsageFlags flag) void VulkanContext::BeginRecord(VkCommandBuffer cmd, VkCommandBufferUsageFlags flag)
{ {
VkCommandBufferBeginInfo beginInfo{ VkCommandBufferBeginInfo beginInfo{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,//sType VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,//sType
nullptr, //pNext nullptr, //pNext
flag //flags flag //flags
}; };
vkBeginCommandBuffer(surfaceCommand, &beginInfo); vkBeginCommandBuffer(cmd, &beginInfo);
} }
void VulkanContext::EndRecord(VkQueue queue) void VulkanContext::EndRecord(VkQueue queue)
@ -105,4 +102,83 @@ namespace vkn {
vkQueueSubmit(queue, 1, &submitInfo, surfaceFence); vkQueueSubmit(queue, 1, &submitInfo, surfaceFence);
graphSemaphore = presentSemaphore; graphSemaphore = presentSemaphore;
} }
void VulkanContext::FlushCommand()
{
if (transferCommand) {
vkEndCommandBuffer(transferCommand);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &transferCommand;
vkQueueSubmit(Backend::RenderWorker->GetQueue().Ptr(), 1, &submitInfo, nullptr);
transferCommand = nullptr;
}
}
VkCommandBuffer VulkanContext::GetTransferCommand()
{
switch (renderPassState)
{
case api::RenderPassState::BeginRecord:
return command;
case api::RenderPassState::BeginRender:
{
if (!transferCommand) {
transferCommand = VulkanWindow::Ptr()->GetTransferCommand(frame);
BeginRecord(transferCommand, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
}
return transferCommand;
}
case api::RenderPassState::Present:
return surfaceCommand;
default:
return nullptr;
}
}
void VulkanContext::ExecuteSurfaceBarriers(const ResourceBarrierDesc& desc)
{
BeginRecord(surfaceCommand, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
ExecuteResourceBarriers(desc);
EndRecord(Backend::RenderWorker->GetQueue().Ptr());
}
void VulkanContext::ExecuteResourceBarriers(const ResourceBarrierDesc& desc) {
pmr::vector<VkBufferMemoryBarrier> bufferBarriers{ FramePool() };
bufferBarriers.reserve(desc.bufferBarriersCount);
pmr::vector<VkImageMemoryBarrier> imageBarriers{ FramePool() };
imageBarriers.reserve(desc.textureBarriersCount);
VkPipelineStageFlags srcStageMask = 0, dstStageMask = 0;
for (uint32_t i = 0; i < desc.textureBarriersCount; i++)
{
auto& barrier = desc.pTextureBarriers[i];
auto desc = vkApiGetTextureTransition(srcStageMask, dstStageMask, barrier);
imageBarriers.push_back(desc);
}
if (dstStageMask == 0) {
dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
}
vkCmdPipelineBarrier(GetTransferCommand(), srcStageMask, dstStageMask, 0, 0, NULL, 0, NULL, imageBarriers.size(), imageBarriers.data());
}
void VulkanContext::UpdateTexture(TextureDesc& texture, const TextureUpdateArgs& update, ResourceState state)
{
if (!texture.id) {
VulkanAPI::Ptr()->graph.AcquireTexture(texture);
}
if (texture.state != state) {
TextureBarrier barrier{};
barrier.mSrcState = texture.state;
barrier.mDstState = state;
barrier.mTexture = texture;
ResourceBarrierDesc desc{};
desc.pTextureBarriers = &barrier;
desc.textureBarriersCount = 1;
ExecuteResourceBarriers(desc);
}
uint32_t texelBytes = texture.format == TinyImageFormat_R8_UNORM ? 1 : 4;
uint32_t size = update.width * update.height * texelBytes;
ImageUpdator updator{};
updator.args = update;
updator.size = size;
updator.image = (VkImage)texture.image;
updator.command = GetTransferCommand();
Backend::TransferWorker->UpdateImage(updator);
}
} }

View File

@ -66,7 +66,7 @@ namespace vkn {
vkGetSwapchainImagesKHR(device.Ptr(), mPtr, &imageCount, swapchain_images.data()); vkGetSwapchainImagesKHR(device.Ptr(), mPtr, &imageCount, swapchain_images.data());
mFences.reserve(mFrames); mFences.reserve(mFrames);
mSurfaces.reserve(imageCount); mSurfaces.reserve(imageCount);
mCommands.reserve(mFrames); mCommands.reserve(mFrames + mFrames);
mSemaphores.reserve(mFrames + mFrames); mSemaphores.reserve(mFrames + mFrames);
TextureDesc desc{}; TextureDesc desc{};
desc.width = args.width; desc.width = args.width;
@ -84,6 +84,7 @@ namespace vkn {
mSemaphores.push_back(mDevice.CreateSemaphore()); mSemaphores.push_back(mDevice.CreateSemaphore());
mSemaphores.push_back(mDevice.CreateSemaphore()); mSemaphores.push_back(mDevice.CreateSemaphore());
mCommands.push_back(Backend::RenderWorker->AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY)); mCommands.push_back(Backend::RenderWorker->AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY));
mCommands.push_back(Backend::RenderWorker->AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY));
mFences.push_back(mDevice.CreateFence(VK_FENCE_CREATE_SIGNALED_BIT)); mFences.push_back(mDevice.CreateFence(VK_FENCE_CREATE_SIGNALED_BIT));
} }
for (int i = mFrames; i < imageCount; i++) { for (int i = mFrames; i < imageCount; i++) {

View File

@ -18,8 +18,14 @@ namespace api {
mView->SetFlags(RenderFlags_PPAA | RenderFlags_LCD); mView->SetFlags(RenderFlags_PPAA | RenderFlags_LCD);
mView->SetSize(1024, 768); mView->SetSize(1024, 768);
mView->GetRenderer()->Init(UIRenderDevice::Ptr()); mView->GetRenderer()->Init(UIRenderDevice::Ptr());
}
void EditorMainWindow::DrawNoesisUI()
{
mView->Update(0.033);
IRenderer* renderer = mView->GetRenderer();
renderer->UpdateRenderTree();
renderer->RenderOffscreen();
renderer->Render();
} }
TextureSampler sampler{ TextureSampler sampler{
.filterMag = SamplerMagFilter::LINEAR, .filterMag = SamplerMagFilter::LINEAR,
@ -79,10 +85,6 @@ namespace api {
InitRenderSurface(graph, ctx.frameCount); InitRenderSurface(graph, ctx.frameCount);
} }
ImGui::End(); ImGui::End();
//mView->Update(0.033); DrawNoesisUI();
//IRenderer* renderer = mView->GetRenderer();
//renderer->UpdateRenderTree();
//renderer->RenderOffscreen();
//renderer->Render();
} }
} }