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:
using UIWindow::UIWindow;
void InitializeComponent() override;
};
class EditorMainWindow : public EditorWindow {
public:
Noesis::Ptr<Noesis::IView> mView;
public:
EditorMainWindow();
void DrawNoesisUI();
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"
namespace api {
SINGLETON_DEFINE(RenderAPI)

View File

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

View File

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

View File

@ -6,6 +6,12 @@ namespace api {
struct FRenderView {
RenderContext* context;
};
enum class RenderPassState : uint8_t {
Default,
BeginRecord,
BeginRender,
Present,
};
struct RenderContext {
pmr::vector<FRenderView> views;
TextureDesc surface;
@ -13,6 +19,7 @@ namespace api {
uint32_t frame{ 0 };
uint32_t presentFrame{ 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 SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 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 DrawIndexed(uint32_t index_count, uint32_t first_index, uint32_t first_vertex) = 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,
};
enum class BufferUsage : uint8_t {
STATIC = 0x01, //!< content modified once, used many times
DYNAMIC = 0x02, //!< content modified frequently, used many times
VERTEX = 0x04,
UNIFORM = 0x08,
SHADER_STORAGE = 0x10,
TRANSFER_SRC = 0x20,
None = 0,
STATIC, //!< content modified once, used many times
DYNAMIC, //!< content modified frequently, used many times
VERTEX,
INDEX,
UNIFORM,
SHADER_STORAGE,
TRANSFER_SRC,
};
/*
@ -343,7 +345,6 @@ namespace api {
return barrier;
}
struct ResourceBarrierDesc {
RenderPassType type;
const BufferBarrier* pBufferBarriers;
uint32_t bufferBarriersCount;
const TextureBarrier* pTextureBarriers;
@ -369,6 +370,7 @@ namespace api {
uint32_t y;
uint32_t width;
uint32_t height;
uint32_t mipLevel;
const void* data;
};
}

View File

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

View File

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

View File

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

View File

@ -30,7 +30,4 @@ namespace api{
bool isInverted = 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_module.h"
#include "ui_render_device_help.inl"
#include "render/render_buffer.h"
#define CBUFFER_SIZE 16 * 1024
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)
UIRenderDevice::UIRenderDevice(RenderAPI* api) : mApi(api)
UIRenderDevice::UIRenderDevice(RenderAPI* api)
{
mImpl = new (GlobalPool()) UIRenderDeviceImpl(api);
SINGLETON_PTR();
}
UIRenderDevice::~UIRenderDevice()
@ -16,7 +44,7 @@ namespace api {
}
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)
{
@ -30,21 +58,23 @@ namespace api {
{
TextureDesc desc{};
desc.id = -1;
desc.format = VKFormat(format, mCaps.linearRendering);
desc.format = VKFormat(format, mImpl->mCaps.linearRendering);
desc.width = width;
desc.height = height;
desc.mipLevel = numLevels;
desc.sampleCount = SAMPLE_COUNT_1;
desc.usage = TextureUsage::SAMPLEABLE | TextureUsage::BLIT_DST;
desc.state = ResourceState::UNDEFINED;
mApi->CreateTexture(desc);
return CreateUITexture(desc);
desc.dimension = TextureDimension::TEX_2D;
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)
{
UITexture* uiTex = (UITexture*)texture;
TextureUpdateArgs args{.x = x, .y = y, .width = width,.height = height, .data = data};
mApi->UpdateTexture(uiTex->desc, args, ResourceState::TRANSFER_DST);
TextureUpdateArgs args{.x = x, .y = y, .width = width,.height = height, .mipLevel = level, .data = data};
mImpl->Context().UpdateTexture(uiTex->desc, args, ResourceState::TRANSFER_DST);
}
void UIRenderDevice::BeginOffscreenRender()
{
@ -104,33 +134,19 @@ namespace api {
}
void* UIRenderDevice::MapVertices(uint32_t bytes)
{
int b = 10000;
for (int a = 1; a < b; a++) {
b--;
}
return nullptr;
auto& ctx = mImpl->Context();
return mImpl->mVertices.MapBuffer(bytes, ctx.frameNumber, ctx.frameNumber - ctx.frameCount);
}
void UIRenderDevice::UnmapVertices()
{
int b = 10000;
for (int a = 1; a < b; a++) {
b--;
}
}
void* UIRenderDevice::MapIndices(uint32_t bytes)
{
int b = 10000;
for (int a = 1; a < b; a++) {
b--;
}
return nullptr;
auto& ctx = mImpl->Context();
return mImpl->mIndices.MapBuffer(bytes, ctx.frameNumber, ctx.frameNumber - ctx.frameCount);
}
void UIRenderDevice::UnmapIndices()
{
int b = 10000;
for (int a = 1; a < b; a++) {
b--;
}
}
void UIRenderDevice::DrawBatch(const Noesis::Batch& batch)
{

View File

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

View File

@ -42,10 +42,10 @@ namespace vkn {
VkImage* image;
};
struct ImageUpdator {
TextureUpdateArgs args;
VkCommandBuffer command;
VkImage image;
uint32_t size;
uint32_t mipLevel;
TextureUpdateArgs args;
};
struct SyncTransferCommand {
uint32_t frameNumber;
@ -85,6 +85,6 @@ namespace vkn {
void UpdateImage(ImageUpdator& elem, TransferBufferType type = TransferBufferType::Graphics);
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/type.h"
#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 {
using pmr::Name;
using pmr::table;

View File

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

View File

@ -1,13 +1,15 @@
#pragma once
#include "type.h"
#include "render/renderapi.h"
#include "render/render_api.h"
namespace vkn {
using api::BufferDesc;
using api::RenderPassState;
struct VulkanContext : public api::RenderContext {
VkFence surfaceFence;
VkSemaphore surfaceSemaphore;
VkSemaphore presentSemaphore;
VkSemaphore graphSemaphore;
VkCommandBuffer transferCommand;
VkCommandBuffer surfaceCommand;
VkCommandBuffer command;
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 DrawIndexed(uint32_t index_count, uint32_t first_index, uint32_t first_vertex) 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 BeginRecord(VkCommandBufferUsageFlags flag);
void BeginRecord(VkCommandBuffer cmd, VkCommandBufferUsageFlags flag);
void EndRecord(VkQueue queue);
void FlushCommand();
VkCommandBuffer GetTransferCommand();
};
}

View File

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

View File

@ -148,13 +148,14 @@ namespace vkn {
allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
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)
{
bool isTransfer = type == TransferBufferType::Transfer;
DynamicBufferPool* pPoolRef;
CommandBuffer command;
CommandBuffer command = elem.command;
if (!BeginDynamicCommand(pPoolRef, command, isTransfer)) {
Invoke(elem);
return;
@ -162,25 +163,29 @@ namespace vkn {
TextureUpdateArgs args = elem.args;
// 将数据复制到 Staging Buffer
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{};
region.imageOffset.x = args.x;
region.imageOffset.y = args.y;
region.imageExtent.width = args.width;
region.imageExtent.height = args.height;
region.imageExtent.depth = 1;
region.imageSubresource.mipLevel = elem.mipLevel;
region.imageSubresource.mipLevel = args.mipLevel;
region.bufferOffset = uploadBuffer->drawPos;
region.imageSubresource.layerCount = 1;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
vkCmdCopyBufferToImage(command.Ptr(), (VkBuffer)uploadBuffer->currentPage->pBuffer, elem.image,
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)
{
pPoolRef = isTransfer ? &mTransferBuffer : &mGraphicsBuffer;
if (command.Ptr()) {
return true;
}
if (pPoolRef->commandIndex >= MAX_TRANSFER_SYNC_FENCES) {
return false;
}
@ -188,7 +193,7 @@ namespace vkn {
command.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
return true;
}
void BufferWorker::EndDynamicCommand(DynamicBufferPool* pPoolRef, CommandBuffer& command, bool isTransfer)
void BufferWorker::EndDynamicCommand(DynamicBufferPool* pPoolRef, CommandBuffer command, bool isTransfer)
{
command.EndRecord();
pPoolRef->commandIndex++;

View File

@ -340,31 +340,6 @@ namespace vkn {
vkCreateSampler(backend.GetDevice().Ptr(), &samplerInfo, nullptr, &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()
{
VulkanContext& ctx = *(VulkanContext*)&context;
@ -375,28 +350,10 @@ namespace vkn {
void VulkanAPI::EndFrame()
{
VulkanContext& ctx = *(VulkanContext*)&context;
ctx.FlushCommand();
window.Present(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)
{
RenderPassKey config{};
@ -481,8 +438,10 @@ namespace vkn {
CommandBuffer cmd = passInfo->commands[context.frame];
ctx.command = cmd.Ptr();
cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
ctx.renderPassState = RenderPassState::BeginRecord;
if(callback) callback(node);
vkCmdBeginRenderPass(cmd.Ptr(), &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
ctx.renderPassState = RenderPassState::BeginRender;
if (clearSurfaceIndex != -1)ctx.ClearSurface(clearValues[clearSurfaceIndex].color);
}
void VulkanAPI::EndRenderPass(RenderPassNode* node)
@ -492,6 +451,7 @@ namespace vkn {
CommandBuffer cmd = passInfo->commands[context.frame];
vkCmdEndRenderPass(cmd.Ptr());
cmd.EndRecord();
ctx.renderPassState = RenderPassState::Default;
VkSemaphore waitSemaphores[8];
VkPipelineStageFlags waitDstStageMasks[8];
uint32_t semaphoreCount = 0;

View File

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

View File

@ -1,6 +1,9 @@
#include "vkn/backend.h"
#include "vkn/vulkan_api.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"
namespace vkn {
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);
}
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)
{
// 条件满足时,手动清除附件
@ -73,14 +70,14 @@ namespace vkn {
// 使用 vkCmdClearAttachments 清除颜色附件
vkCmdClearAttachments(command, 1, &clearAttachment, 1, &clearRect);
}
void VulkanContext::BeginRecord(VkCommandBufferUsageFlags flag)
void VulkanContext::BeginRecord(VkCommandBuffer cmd, VkCommandBufferUsageFlags flag)
{
VkCommandBufferBeginInfo beginInfo{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,//sType
nullptr, //pNext
flag //flags
};
vkBeginCommandBuffer(surfaceCommand, &beginInfo);
vkBeginCommandBuffer(cmd, &beginInfo);
}
void VulkanContext::EndRecord(VkQueue queue)
@ -105,4 +102,83 @@ namespace vkn {
vkQueueSubmit(queue, 1, &submitInfo, surfaceFence);
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());
mFences.reserve(mFrames);
mSurfaces.reserve(imageCount);
mCommands.reserve(mFrames);
mCommands.reserve(mFrames + mFrames);
mSemaphores.reserve(mFrames + mFrames);
TextureDesc desc{};
desc.width = args.width;
@ -84,6 +84,7 @@ namespace vkn {
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));
mFences.push_back(mDevice.CreateFence(VK_FENCE_CREATE_SIGNALED_BIT));
}
for (int i = mFrames; i < imageCount; i++) {

View File

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