add dynamic buffer & add noesis
2
engine/3rdparty/xmake.lua
vendored
@ -1,4 +1,4 @@
|
||||
add_requires("spdlog", "vulkansdk","shaderc","spirv","spirv-cross")
|
||||
add_requires("spdlog", "vulkansdk","shaderc","spirv","spirv-cross","stb")
|
||||
add_requires("mimalloc", {configs = {shared = true, debug = true, copy = true}})
|
||||
--add_requires("imgui",{configs = {shared = true, debug = true, copy = true}})
|
||||
add_requires("noesis",{configs = {shared = true, copy = true}})
|
||||
|
||||
BIN
engine/assets/noesis/Fonts/Aero Matics Regular.ttf
Normal file
BIN
engine/assets/noesis/Fonts/Caladea-Regular.ttf
Normal file
BIN
engine/assets/noesis/Fonts/CourierPrime-Regular.ttf
Normal file
BIN
engine/assets/noesis/Fonts/Muli-Bold.ttf
Normal file
BIN
engine/assets/noesis/Fonts/Muli-Italic.ttf
Normal file
BIN
engine/assets/noesis/Fonts/Muli-Regular.ttf
Normal file
BIN
engine/assets/noesis/Fonts/WidgetIcons.ttf
Normal file
BIN
engine/assets/noesis/Images/Nature.png
Normal file
|
After Width: | Height: | Size: 448 KiB |
BIN
engine/assets/noesis/Images/file.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
engine/assets/noesis/Images/floppy-disk.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
engine/assets/noesis/Images/folder-closed.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
engine/assets/noesis/Images/folder-open.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
engine/assets/noesis/Images/recycling-bin.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
engine/assets/noesis/Images/search.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
16
engine/assets/noesis/Menu.xaml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<UserControl x:Class="api.UIWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:api"
|
||||
Height="300" Width="400">
|
||||
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
|
||||
<TextBlock Name="HelloText" Text="Hello, Noesis GUI!" FontSize="24" Margin="10"/>
|
||||
|
||||
<Button Content="Click Me" Width="200" Height="50" Margin="10"/>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
</UserControl>
|
||||
@ -1,4 +1,10 @@
|
||||
#pragma once
|
||||
#include "ui/ui_window.h"
|
||||
namespace api {
|
||||
class EditorMainWindow : public UIWindow {
|
||||
public:
|
||||
using UIWindow::UIWindow;
|
||||
void InitializeComponent() override;
|
||||
|
||||
};
|
||||
}
|
||||
@ -2,5 +2,4 @@
|
||||
#include "data/global.h"
|
||||
namespace api {
|
||||
APP_API EngineConfig gEngineConfig{};
|
||||
IMPLEMENT_STATIC_MODULE(APP_API, AppModule, app)
|
||||
}
|
||||
@ -298,6 +298,5 @@ namespace api {
|
||||
{
|
||||
impl->SetFileFlag(name, flag);
|
||||
}
|
||||
IMPLEMENT_STATIC_MODULE(ASSET_API, AssetModule, asset)
|
||||
}
|
||||
|
||||
|
||||
@ -246,5 +246,4 @@ namespace api {
|
||||
{
|
||||
return impl->spawnStaticModule(name);
|
||||
}
|
||||
IMPLEMENT_STATIC_MODULE(CORE_API, CoreModule, core)
|
||||
}
|
||||
@ -66,5 +66,6 @@ namespace api
|
||||
return "";
|
||||
}
|
||||
pmr::string RealPath()const;
|
||||
static pmr::string RealPath(const char* str);
|
||||
};
|
||||
}
|
||||
@ -5,5 +5,9 @@ namespace api {
|
||||
{
|
||||
return FileManager::Ptr()->RealPath(*this);
|
||||
}
|
||||
pmr::string PackagePath::RealPath(const char* str)
|
||||
{
|
||||
return FileManager::Ptr()->RealPath(str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
#include "render/render_module.h"
|
||||
namespace api {
|
||||
SINGLETON_DEFINE(RenderAPI)
|
||||
IMPLEMENT_STATIC_MODULE(RENDER_API, RenderModule, render);
|
||||
void RenderAPI::RenderView(FRenderView& view)
|
||||
{
|
||||
view.context = &context;
|
||||
|
||||
@ -7,7 +7,7 @@ namespace api {
|
||||
{
|
||||
public:
|
||||
struct TextureID{
|
||||
uint32_t id;
|
||||
int32_t id;
|
||||
uint32_t tick;
|
||||
};
|
||||
uint32_t mTickStamp{1};
|
||||
@ -45,7 +45,7 @@ namespace api {
|
||||
void TransitionState(TextureDesc& desc, ResourceState state);
|
||||
bool ResolveState(TextureDesc& desc, ResourceState& srcstart, ResourceState& dststate);
|
||||
bool ResolveState(BufferDesc& desc, ResourceState& srcstart, ResourceState& dststate);
|
||||
TextureDesc& ResolveTexture(uint32_t id);
|
||||
TextureDesc& ResolveTexture(int32_t id);
|
||||
TextureDesc ResourceTexture(Name name, int num);
|
||||
ImageViewPtr ResolveTextureView(TextureDesc& desc);
|
||||
ImageViewPtr ResolveTextureView(TextureViewKey key);
|
||||
|
||||
144
engine/modules/engine/render/include/render/render_buffer.h
Normal file
@ -0,0 +1,144 @@
|
||||
#pragma once
|
||||
#define PREALLOCATED_DYNAMIC_BUFFER_PAGES 2
|
||||
#include "renderapi.h"
|
||||
namespace api {
|
||||
struct DynamicBufferDesc {
|
||||
uint32_t size;
|
||||
uint32_t pos;
|
||||
uint32_t drawPos;
|
||||
BufferUsage usage;
|
||||
ResourceMemoryUsage memoryUsage;
|
||||
};
|
||||
struct DynamicBuffer : public DynamicBufferDesc
|
||||
{
|
||||
struct Page
|
||||
{
|
||||
uint32_t hash;
|
||||
uint32_t frameNumber;
|
||||
void* pBuffer;
|
||||
void* pAllocation;
|
||||
void* pMappingAddr;
|
||||
Page* next;
|
||||
};
|
||||
struct PageAllocator
|
||||
{
|
||||
struct Block
|
||||
{
|
||||
Page pages[16];
|
||||
Block* next;
|
||||
};
|
||||
uint32_t pageIndex;
|
||||
uint32_t numPages;
|
||||
Block* blocks = nullptr;
|
||||
};
|
||||
Page* currentPage;
|
||||
Page* freePages;
|
||||
Page* pendingPages;
|
||||
PageAllocator allocator;
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void InitBuffer(uint32_t _size, BufferUsage _usage, ResourceMemoryUsage _memoryUsage)
|
||||
{
|
||||
pos = 0;
|
||||
drawPos = 0;
|
||||
size = _size;
|
||||
usage = _usage;
|
||||
memoryUsage = _memoryUsage;
|
||||
|
||||
pendingPages = nullptr;
|
||||
freePages = nullptr;
|
||||
allocator.numPages = 0;
|
||||
allocator.pageIndex = 0;
|
||||
for (uint32_t i = 0; i < PREALLOCATED_DYNAMIC_BUFFER_PAGES; i++)
|
||||
{
|
||||
Page* page = AllocatePage();
|
||||
page->next = freePages;
|
||||
freePages = page;
|
||||
}
|
||||
|
||||
currentPage = freePages;
|
||||
freePages = freePages->next;
|
||||
}
|
||||
static Page* AllocatePageMemory(PageAllocator& allocator)
|
||||
{
|
||||
using Block = PageAllocator::Block;
|
||||
if (!allocator.blocks || allocator.pageIndex == _countof(Block::pages))
|
||||
{
|
||||
Block* block = (Block*)xmalloc(sizeof(Block));
|
||||
block->next = allocator.blocks;
|
||||
allocator.blocks = block;
|
||||
allocator.pageIndex = 0;
|
||||
}
|
||||
allocator.numPages++;
|
||||
return allocator.blocks->pages + allocator.pageIndex++;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Page* AllocatePage()
|
||||
{
|
||||
Page* page = AllocatePageMemory(allocator);
|
||||
memset(page, 0, sizeof(Page));
|
||||
BufferDesc desc{};
|
||||
desc.size = size;
|
||||
desc.usage = usage;
|
||||
desc.memoryUsage = memoryUsage;
|
||||
RenderAPI::Ptr()->CreateBuffer(desc);
|
||||
page->pAllocation = desc.pAllocation;
|
||||
page->pBuffer = desc.buffer;
|
||||
page->pMappingAddr = desc.pMappingAddr;
|
||||
return page;
|
||||
}
|
||||
void* MapBuffer(uint32_t _size, uint32_t frameNumber, uint32_t safeFrameNumber) {
|
||||
if (pos + _size > size)
|
||||
{
|
||||
// We ran out of space in the current page, get a new one
|
||||
// Move the current one to pending and insert a GPU fence
|
||||
currentPage->frameNumber = frameNumber;
|
||||
currentPage->next = pendingPages;
|
||||
pendingPages = currentPage;
|
||||
|
||||
// If there is one free slot get it
|
||||
if (freePages != nullptr)
|
||||
{
|
||||
currentPage = freePages;
|
||||
freePages = freePages->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move pages already processed by GPU from pending to free
|
||||
Page** it = &pendingPages->next;
|
||||
while (*it != nullptr)
|
||||
{
|
||||
if ((*it)->frameNumber > safeFrameNumber)
|
||||
{
|
||||
it = &((*it)->next);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Once we find a processed page, the rest of pages must be also processed
|
||||
Page* page = *it;
|
||||
*it = nullptr;
|
||||
|
||||
freePages = page;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (freePages != nullptr)
|
||||
{
|
||||
currentPage = freePages;
|
||||
freePages = freePages->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentPage = AllocatePage();
|
||||
}
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
drawPos = pos;
|
||||
pos = pos + _size;
|
||||
return (uint8_t*)currentPage->pMappingAddr + drawPos;
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -12,6 +12,7 @@ namespace api {
|
||||
uint32_t frameCount{0};
|
||||
uint32_t frame{ 0 };
|
||||
uint32_t presentFrame{ 0 };
|
||||
uint32_t frameNumber{ 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 BindIndexBuffer(BufferDesc desc, uint32_t index_stride) = 0;
|
||||
|
||||
@ -38,21 +38,49 @@ namespace api {
|
||||
DYNAMIC = 0x02, //!< content modified frequently, used many times
|
||||
VERTEX = 0x04,
|
||||
UNIFORM = 0x08,
|
||||
SHADER_STORAGE = 0x10
|
||||
SHADER_STORAGE = 0x10,
|
||||
TRANSFER_SRC = 0x20,
|
||||
};
|
||||
enum class ResourceMemoryUsage : uint8_t
|
||||
/*
|
||||
扩展的内存用途标志:
|
||||
GPU_RENDERING:专门为渲染操作设计的内存,常用于存储纹理、帧缓冲等图形资源。
|
||||
GPU_STORAGE:用于存储不需要频繁更新的数据,例如大容量缓冲区或其他不常变动的资源。
|
||||
GPU_COMPUTE:用于计算着色器或其他 GPU 计算任务。可以是读取和写入的内存类型,但它主要用于计算而非渲染。
|
||||
|
||||
与主机的交互:
|
||||
HOST_VISIBLE:标志该内存可以被主机访问,适用于从 CPU 到 GPU 或反向传输的场景。
|
||||
HOST_COHERENT:标志该内存在 CPU 和 GPU 之间的一致性,不需要显式同步。
|
||||
|
||||
懒加载和静态数据:
|
||||
LAZY_ALLOCATED:懒加载内存,适用于 GPU 程序中的延迟加载资源。
|
||||
STATIC:静态数据,如常量缓冲区、着色器程序,通常在初始化时填充并且在后续使用中不变化。
|
||||
*/
|
||||
enum class ResourceMemoryUsage : uint16_t
|
||||
{
|
||||
/// No intended memory usage specified.
|
||||
UNKNOWN = 0,
|
||||
/// Memory will be used on device only, no need to be mapped on host.
|
||||
GPU_ONLY = 1,
|
||||
GPU_ONLY = 0x01,
|
||||
/// Memory will be mapped on host. Could be used for transfer to device.
|
||||
CPU_ONLY = 2,
|
||||
CPU_ONLY = 0x02,
|
||||
/// Memory will be used for frequent (dynamic) updates from host and reads on device.
|
||||
CPU_TO_GPU = 3,
|
||||
CPU_TO_GPU = 0x04,
|
||||
/// Memory will be used for writing on device and readback on host.
|
||||
GPU_TO_CPU = 4,
|
||||
COUNT,
|
||||
GPU_TO_CPU = 0x08,
|
||||
/// Memory is intended to be used for rendering or graphics purposes.
|
||||
GPU_RENDERING = 0x10,
|
||||
/// Memory will be used for storage or large buffers that don't require frequent updates.
|
||||
GPU_STORAGE = 0x20,
|
||||
/// Memory is visible to the host and the device, can be used for both read and write.
|
||||
HOST_VISIBLE = 0x40,
|
||||
/// Memory will be lazily allocated and can be used for GPU resources that are not immediately needed.
|
||||
LAZY_ALLOCATED = 0x80,
|
||||
/// Memory is coherent for both host and device, meaning no explicit synchronization is needed.
|
||||
HOST_COHERENT = 0x100,
|
||||
/// Static data, such as constant buffers or shader resources, that will not change after initialization.
|
||||
STATIC = 0x200,
|
||||
/// Memory intended for use by a compute shader, can be mapped or un-mapped depending on use case.
|
||||
GPU_COMPUTE = 0x400,
|
||||
};
|
||||
enum SampleCount : uint8_t
|
||||
{
|
||||
@ -198,9 +226,10 @@ namespace api {
|
||||
struct BufferBarrier;
|
||||
struct TextureBarrier;
|
||||
struct BufferDesc {
|
||||
BufferPtr buffer;
|
||||
void* mappingAddr;
|
||||
uint32_t size;
|
||||
BufferPtr buffer;
|
||||
void* pAllocation;
|
||||
void* pMappingAddr;
|
||||
uint32_t size;
|
||||
BufferUsage usage;
|
||||
ResourceMemoryUsage memoryUsage;
|
||||
static BufferDesc Make() {
|
||||
@ -228,7 +257,7 @@ namespace api {
|
||||
}
|
||||
};
|
||||
struct TextureKey {
|
||||
uint32_t id;
|
||||
int32_t id;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint16_t depth;
|
||||
@ -335,6 +364,13 @@ namespace api {
|
||||
float clearDepth;
|
||||
uint32_t clearStencil;
|
||||
};
|
||||
struct TextureUpdateArgs {
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
const void* data;
|
||||
};
|
||||
}
|
||||
#include "meta/hash.h"
|
||||
namespace std {
|
||||
|
||||
@ -36,6 +36,7 @@ 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);
|
||||
|
||||
@ -231,9 +231,9 @@ namespace api {
|
||||
{
|
||||
return true;
|
||||
}
|
||||
TextureDesc& FrameGraph::ResolveTexture(uint32_t id)
|
||||
TextureDesc& FrameGraph::ResolveTexture(int32_t id)
|
||||
{
|
||||
if (!id || id > mTexturePool.size()) {
|
||||
if (id <= 0 || id > mTexturePool.size()) {
|
||||
return mTexturePool[0];//empty
|
||||
}
|
||||
TextureDesc& texture = mTexturePool[id - 1];
|
||||
@ -292,6 +292,7 @@ namespace api {
|
||||
if (it != mTextureKeyMap.end()) {
|
||||
for (auto& id : it->second) {
|
||||
if (id.tick != mTickStamp) {
|
||||
id.tick = mTickStamp;
|
||||
desc.id = id.id;
|
||||
return;
|
||||
}
|
||||
|
||||
36
engine/modules/engine/ui/impl/ui_render_device_help.inl
Normal file
@ -0,0 +1,36 @@
|
||||
#include <NoesisPCH.h>
|
||||
namespace api{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static TinyImageFormat VKFormat(Noesis::TextureFormat::Enum format, bool sRGB)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case Noesis::TextureFormat::RGBA8: return sRGB ? TinyImageFormat_B8G8R8A8_SRGB : TinyImageFormat_B8G8R8A8_UNORM;
|
||||
case Noesis::TextureFormat::RGBX8: return sRGB ? TinyImageFormat_B8G8R8A8_SRGB : TinyImageFormat_B8G8R8A8_UNORM;
|
||||
case Noesis::TextureFormat::R8: return TinyImageFormat_R8_UNORM;
|
||||
default: NS_ASSERT_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class UITexture final : public Noesis::Texture
|
||||
{
|
||||
public:
|
||||
UITexture(TextureDesc desc) : desc(desc) {}
|
||||
~UITexture()
|
||||
{
|
||||
|
||||
}
|
||||
uint32_t GetWidth() const override { return desc.width; }
|
||||
uint32_t GetHeight() const override { return desc.height; }
|
||||
bool HasMipMaps() const override { return desc.mipLevel > 1; }
|
||||
bool IsInverted() const override { return isInverted; }
|
||||
bool HasAlpha() const override { return hasAlpha; }
|
||||
|
||||
TextureDesc desc;
|
||||
bool isInverted = false;
|
||||
bool hasAlpha = false;
|
||||
};
|
||||
static Noesis::Ptr<Noesis::Texture> CreateUITexture(TextureDesc& desc) {
|
||||
return Noesis::MakePtr<UITexture>(desc);
|
||||
}
|
||||
}
|
||||
141
engine/modules/engine/ui/impl/ui_render_device_impl.inl
Normal file
@ -0,0 +1,141 @@
|
||||
#include "ui/ui_render_device.h"
|
||||
#include "ui/ui_module.h"
|
||||
#include "ui_render_device_help.inl"
|
||||
namespace api {
|
||||
SINGLETON_DEFINE(UIRenderDevice)
|
||||
UIRenderDevice::UIRenderDevice(RenderAPI* api) : mApi(api)
|
||||
{
|
||||
SINGLETON_PTR();
|
||||
}
|
||||
UIRenderDevice::~UIRenderDevice()
|
||||
{
|
||||
int b = 10000;
|
||||
for (int a = 1; a < b; a++) {
|
||||
b--;
|
||||
}
|
||||
}
|
||||
const Noesis::DeviceCaps& UIRenderDevice::GetCaps() const
|
||||
{
|
||||
return mCaps;
|
||||
}
|
||||
Noesis::Ptr<Noesis::RenderTarget> UIRenderDevice::CreateRenderTarget(const char* label, uint32_t width, uint32_t height, uint32_t sampleCount, bool needsStencil)
|
||||
{
|
||||
return Noesis::Ptr<Noesis::RenderTarget>();
|
||||
}
|
||||
Noesis::Ptr<Noesis::RenderTarget> UIRenderDevice::CloneRenderTarget(const char* label, Noesis::RenderTarget* surface)
|
||||
{
|
||||
return Noesis::Ptr<Noesis::RenderTarget>();
|
||||
}
|
||||
Noesis::Ptr<Noesis::Texture> UIRenderDevice::CreateTexture(const char* label, uint32_t width, uint32_t height, uint32_t numLevels, Noesis::TextureFormat::Enum format, const void** data)
|
||||
{
|
||||
TextureDesc desc{};
|
||||
desc.id = -1;
|
||||
desc.format = VKFormat(format, 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);
|
||||
}
|
||||
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;
|
||||
|
||||
}
|
||||
void UIRenderDevice::BeginOffscreenRender()
|
||||
{
|
||||
int b = 10000;
|
||||
for (int a = 1; a < b; a++) {
|
||||
b--;
|
||||
}
|
||||
}
|
||||
void UIRenderDevice::EndOffscreenRender()
|
||||
{
|
||||
int b = 10000;
|
||||
for (int a = 1; a < b; a++) {
|
||||
b--;
|
||||
}
|
||||
}
|
||||
void UIRenderDevice::BeginOnscreenRender()
|
||||
{
|
||||
int b = 10000;
|
||||
for (int a = 1; a < b; a++) {
|
||||
b--;
|
||||
}
|
||||
}
|
||||
void UIRenderDevice::EndOnscreenRender()
|
||||
{
|
||||
int b = 10000;
|
||||
for (int a = 1; a < b; a++) {
|
||||
b--;
|
||||
}
|
||||
}
|
||||
void UIRenderDevice::SetRenderTarget(Noesis::RenderTarget* surface)
|
||||
{
|
||||
int b = 10000;
|
||||
for (int a = 1; a < b; a++) {
|
||||
b--;
|
||||
}
|
||||
}
|
||||
void UIRenderDevice::BeginTile(Noesis::RenderTarget* surface, const Noesis::Tile& tile)
|
||||
{
|
||||
int b = 10000;
|
||||
for (int a = 1; a < b; a++) {
|
||||
b--;
|
||||
}
|
||||
}
|
||||
void UIRenderDevice::EndTile(Noesis::RenderTarget* surface)
|
||||
{
|
||||
int b = 10000;
|
||||
for (int a = 1; a < b; a++) {
|
||||
b--;
|
||||
}
|
||||
}
|
||||
void UIRenderDevice::ResolveRenderTarget(Noesis::RenderTarget* surface, const Noesis::Tile* tiles, uint32_t numTiles)
|
||||
{
|
||||
int b = 10000;
|
||||
for (int a = 1; a < b; a++) {
|
||||
b--;
|
||||
}
|
||||
}
|
||||
void* UIRenderDevice::MapVertices(uint32_t bytes)
|
||||
{
|
||||
int b = 10000;
|
||||
for (int a = 1; a < b; a++) {
|
||||
b--;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
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;
|
||||
}
|
||||
void UIRenderDevice::UnmapIndices()
|
||||
{
|
||||
int b = 10000;
|
||||
for (int a = 1; a < b; a++) {
|
||||
b--;
|
||||
}
|
||||
}
|
||||
void UIRenderDevice::DrawBatch(const Noesis::Batch& batch)
|
||||
{
|
||||
int b = 10000;
|
||||
for (int a = 1; a < b; a++) {
|
||||
b--;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
engine/modules/engine/ui/include/ui/noesis_font_provider.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <NsGui/FontProvider.h>
|
||||
namespace api {
|
||||
class UI_API NoesisFontProvider : public Noesis::FontProvider
|
||||
{
|
||||
public:
|
||||
NoesisFontProvider();
|
||||
~NoesisFontProvider();
|
||||
|
||||
private:
|
||||
/// From FontProvider
|
||||
//@{
|
||||
Noesis::FontSource MatchFont(const Noesis::Uri& baseUri, const char* familyName,
|
||||
Noesis::FontWeight& weight, Noesis::FontStretch& stretch, Noesis::FontStyle& style) override;
|
||||
bool FamilyExists(const Noesis::Uri& baseUri, const char* familyName) override;
|
||||
//@}
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <NsGui/TextureProvider.h>
|
||||
namespace api {
|
||||
class UI_API NoesisTextureProvider : public Noesis::TextureProvider
|
||||
{
|
||||
public:
|
||||
NoesisTextureProvider();
|
||||
~NoesisTextureProvider();
|
||||
|
||||
private:
|
||||
/// From TextureProvider
|
||||
//@{
|
||||
Noesis::TextureInfo GetTextureInfo(const Noesis::Uri& uri) override;
|
||||
Noesis::Ptr<Noesis::Texture> LoadTexture(const Noesis::Uri& uri, Noesis::RenderDevice* device) override;
|
||||
};
|
||||
}
|
||||
17
engine/modules/engine/ui/include/ui/noesis_xaml_provider.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <NsGui/XamlProvider.h>
|
||||
namespace api {
|
||||
class UI_API NoesisXamlProvider : public Noesis::XamlProvider
|
||||
{
|
||||
public:
|
||||
NoesisXamlProvider();
|
||||
~NoesisXamlProvider();
|
||||
|
||||
private:
|
||||
/// From XamlProvider
|
||||
//@{
|
||||
Noesis::Ptr<Noesis::Stream> LoadXaml(const Noesis::Uri& uri) override;
|
||||
//@}
|
||||
|
||||
};
|
||||
}
|
||||
@ -7,5 +7,8 @@ namespace api {
|
||||
void OnLoad(int argc, char** argv) override;
|
||||
void OnUnload() override;
|
||||
void InitMetaData(void) override {};
|
||||
void Initialize()override;
|
||||
|
||||
void SetThemeProviders();
|
||||
};
|
||||
}
|
||||
41
engine/modules/engine/ui/include/ui/ui_render_device.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include "render/renderapi.h"
|
||||
#include <NsRender/RenderDevice.h>
|
||||
namespace api {
|
||||
class UI_API UIRenderDevice final : public Noesis::RenderDevice {
|
||||
private:
|
||||
RenderAPI* mApi;
|
||||
Noesis::DeviceCaps mCaps;
|
||||
SINGLETON_IMPL(UIRenderDevice)
|
||||
public:
|
||||
UIRenderDevice(RenderAPI* api);
|
||||
~UIRenderDevice();
|
||||
private:
|
||||
/// From RenderDevice
|
||||
//@{
|
||||
const Noesis::DeviceCaps& GetCaps() const override;
|
||||
Noesis::Ptr<Noesis::RenderTarget> CreateRenderTarget(const char* label, uint32_t width,
|
||||
uint32_t height, uint32_t sampleCount, bool needsStencil) override;
|
||||
Noesis::Ptr<Noesis::RenderTarget> CloneRenderTarget(const char* label,
|
||||
Noesis::RenderTarget* surface) override;
|
||||
Noesis::Ptr<Noesis::Texture> CreateTexture(const char* label, uint32_t width, uint32_t height,
|
||||
uint32_t numLevels, Noesis::TextureFormat::Enum format, const void** data) override;
|
||||
void UpdateTexture(Noesis::Texture* texture, uint32_t level, uint32_t x, uint32_t y,
|
||||
uint32_t width, uint32_t height, const void* data) override;
|
||||
void BeginOffscreenRender() override;
|
||||
void EndOffscreenRender() override;
|
||||
void BeginOnscreenRender() override;
|
||||
void EndOnscreenRender() override;
|
||||
void SetRenderTarget(Noesis::RenderTarget* surface) override;
|
||||
void BeginTile(Noesis::RenderTarget* surface, const Noesis::Tile& tile) override;
|
||||
void EndTile(Noesis::RenderTarget* surface) override;
|
||||
void ResolveRenderTarget(Noesis::RenderTarget* surface, const Noesis::Tile* tiles,
|
||||
uint32_t numTiles) override;
|
||||
void* MapVertices(uint32_t bytes) override;
|
||||
void UnmapVertices() override;
|
||||
void* MapIndices(uint32_t bytes) override;
|
||||
void UnmapIndices() override;
|
||||
void DrawBatch(const Noesis::Batch& batch) override;
|
||||
//@}
|
||||
};
|
||||
}
|
||||
19
engine/modules/engine/ui/include/ui/ui_window.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <NsCore/Noesis.h>
|
||||
#include <NsGui/UserControl.h>
|
||||
#include <NsCore/ReflectionDeclare.h>
|
||||
namespace api {
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Provides the ability to create, configure, show, and manage the lifetime of windows.
|
||||
///
|
||||
/// http://msdn.microsoft.com/en-us/library/system.windows.window.aspx
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class UIWindow : public Noesis::UserControl
|
||||
{
|
||||
public:
|
||||
UIWindow();
|
||||
~UIWindow();
|
||||
virtual void InitializeComponent();
|
||||
NS_DECLARE_REFLECTION(UIWindow, Noesis::UserControl)
|
||||
};
|
||||
}
|
||||
27
engine/modules/engine/ui/src/noesis_font_provider.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "ui/noesis_font_provider.h"
|
||||
#include <NsGui/Uri.h>
|
||||
#include <NsGui/Stream.h>
|
||||
namespace api {
|
||||
using namespace Noesis;
|
||||
NoesisFontProvider::NoesisFontProvider()
|
||||
{
|
||||
|
||||
}
|
||||
NoesisFontProvider::~NoesisFontProvider()
|
||||
{
|
||||
}
|
||||
FontSource NoesisFontProvider::MatchFont(const Uri& baseUri, const char* familyName, FontWeight& weight, FontStretch& stretch, FontStyle& style)
|
||||
{
|
||||
auto uri = baseUri;
|
||||
auto a1 = uri.Str();
|
||||
auto a2 = uri.FullPath();
|
||||
return FontSource();
|
||||
}
|
||||
bool NoesisFontProvider::FamilyExists(const Uri& baseUri, const char* familyName)
|
||||
{
|
||||
auto uri = baseUri;
|
||||
auto a1 = uri.Str();
|
||||
auto a2 = uri.FullPath();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
65
engine/modules/engine/ui/src/noesis_texture_provider.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#include "ui/noesis_texture_provider.h"
|
||||
#include "os/package_path.h"
|
||||
#include <NsGui/Uri.h>
|
||||
#include <NsGui/Stream.h>
|
||||
#include <NsCore/Log.h>
|
||||
#include <NsRender/Texture.h>
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
namespace api {
|
||||
using namespace Noesis;
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static int Read(void* user, char* data, int size)
|
||||
{
|
||||
Stream* stream = (Stream*)user;
|
||||
return stream->Read(data, size);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static void Skip(void* user, int n)
|
||||
{
|
||||
Stream* stream = (Stream*)user;
|
||||
stream->SetPosition((int)stream->GetPosition() + n);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static int Eof(void* user)
|
||||
{
|
||||
Stream* stream = (Stream*)user;
|
||||
return stream->GetPosition() >= stream->GetLength();
|
||||
}
|
||||
NoesisTextureProvider::NoesisTextureProvider()
|
||||
{
|
||||
|
||||
}
|
||||
NoesisTextureProvider::~NoesisTextureProvider()
|
||||
{
|
||||
}
|
||||
TextureInfo NoesisTextureProvider::GetTextureInfo(const Uri& uri)
|
||||
{
|
||||
TextureInfo info;
|
||||
Ptr<Stream> file = OpenFileStream(PackagePath::RealPath(uri.FullPath()).c_str());
|
||||
if (file != 0)
|
||||
{
|
||||
int x, y, n;
|
||||
stbi_io_callbacks callbacks = { Read, Skip, Eof };
|
||||
if (stbi_info_from_callbacks(&callbacks, file, &x, &y, &n))
|
||||
{
|
||||
info.width = x;
|
||||
info.height = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARNING("%s: %s", uri.Str(), stbi_failure_reason());
|
||||
}
|
||||
file->Close();
|
||||
}
|
||||
return info;
|
||||
}
|
||||
Ptr<Texture> NoesisTextureProvider::LoadTexture(const Uri& uri, RenderDevice* device)
|
||||
{
|
||||
auto a1 = uri.Str();
|
||||
auto a2 = uri.FullPath();
|
||||
return Ptr<Texture>();
|
||||
}
|
||||
}
|
||||
18
engine/modules/engine/ui/src/noesis_xaml_provider.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include "ui/noesis_xaml_provider.h"
|
||||
#include "os/package_path.h"
|
||||
#include <NsGui/Uri.h>
|
||||
#include <NsGui/Stream.h>
|
||||
namespace api {
|
||||
using namespace Noesis;
|
||||
NoesisXamlProvider::NoesisXamlProvider()
|
||||
{
|
||||
|
||||
}
|
||||
NoesisXamlProvider::~NoesisXamlProvider()
|
||||
{
|
||||
}
|
||||
Ptr<Stream> NoesisXamlProvider::LoadXaml(const Uri& uri)
|
||||
{
|
||||
return OpenFileStream(PackagePath::RealPath(uri.FullPath()).c_str());
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,18 @@
|
||||
#include "zlog.h"
|
||||
#include "ui/ui_module.h"
|
||||
#include "NoesisPCH.h"
|
||||
#include "ui/ui_window.h"
|
||||
#include "ui/ui_render_device.h"
|
||||
#include "ui/noesis_xaml_provider.h"
|
||||
#include "ui/noesis_font_provider.h"
|
||||
#include "ui/noesis_texture_provider.h"
|
||||
#include <NsGui/IntegrationAPI.h>
|
||||
#include <NsGui/FontProperties.h>
|
||||
#include <NsCore/RegisterComponent.inl>
|
||||
namespace api {
|
||||
using namespace Noesis;
|
||||
void UIModule::OnLoad(int argc, char** argv)
|
||||
{
|
||||
Noesis::SetLogHandler([](const char*, uint32_t, uint32_t level, const char*, const char* msg)
|
||||
SetLogHandler([](const char*, uint32_t, uint32_t level, const char*, const char* msg)
|
||||
{
|
||||
switch (level) {
|
||||
case 0:
|
||||
@ -23,12 +31,31 @@ namespace api {
|
||||
}
|
||||
});
|
||||
// Sets the active license
|
||||
Noesis::GUI::SetLicense(NS_LICENSE_NAME, NS_LICENSE_KEY);
|
||||
GUI::SetLicense(NS_LICENSE_NAME, NS_LICENSE_KEY);
|
||||
// Noesis initialization. This must be the first step before using any NoesisGUI functionality
|
||||
Noesis::GUI::Init();
|
||||
GUI::Init();
|
||||
}
|
||||
void UIModule::OnUnload()
|
||||
{
|
||||
|
||||
// 清理资源提供者
|
||||
GUI::SetFontProvider(nullptr);
|
||||
GUI::SetTextureProvider(nullptr);
|
||||
}
|
||||
void UIModule::Initialize()
|
||||
{
|
||||
IStaticModule::Initialize();
|
||||
GUI::SetXamlProvider(new NoesisXamlProvider());
|
||||
GUI::SetFontProvider(new NoesisFontProvider());
|
||||
GUI::SetTextureProvider(new NoesisTextureProvider());
|
||||
RegisterComponent<api::UIWindow>();
|
||||
SetThemeProviders();
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void UIModule::SetThemeProviders()
|
||||
{
|
||||
const char* fonts[] = {"Arial"};
|
||||
|
||||
GUI::SetFontFallbacks(fonts, NS_COUNTOF(fonts));
|
||||
GUI::SetFontDefaultProperties(15.0f, FontWeight_Normal, FontStretch_Normal, FontStyle_Normal);
|
||||
}
|
||||
}
|
||||
21
engine/modules/engine/ui/src/ui_window.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "ui/ui_window.h"
|
||||
namespace api {
|
||||
UIWindow::UIWindow()
|
||||
{
|
||||
|
||||
}
|
||||
UIWindow::~UIWindow()
|
||||
{
|
||||
}
|
||||
void UIWindow::InitializeComponent()
|
||||
{
|
||||
|
||||
}
|
||||
NS_IMPLEMENT_REFLECTION(UIWindow,"api.UIWindow")
|
||||
{
|
||||
int A = 1;
|
||||
if (NS_UNLIKELY(A == 0)) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,4 +2,4 @@ static_component("ui","engine")
|
||||
add_headerfiles("include/**.h")
|
||||
add_files("src/**.cpp")
|
||||
add_deps("core", "asset", "zlib", "render")
|
||||
add_packages("noesis", {public = true})
|
||||
add_packages("noesis", "stb", {public = true})
|
||||
@ -1,6 +1,6 @@
|
||||
#include "name.h"
|
||||
constexpr inline size_t meta_align_size(size_t size, size_t alignment = 8) {
|
||||
return (size + alignment - 1) / alignment * alignment;
|
||||
return (size + (alignment - 1)) & ~(alignment - 1);
|
||||
}
|
||||
XMALLOC_API void* xmalloc(size_t size);
|
||||
namespace pmr {
|
||||
|
||||
@ -26,6 +26,5 @@ namespace vkn {
|
||||
public:
|
||||
static struct BufferWorker* TransferWorker;
|
||||
static struct CommandWorker* RenderWorker;
|
||||
static struct CommandWorker* PresentWorker;
|
||||
};
|
||||
};
|
||||
@ -1,17 +1,22 @@
|
||||
#pragma once
|
||||
#include "worker.h"
|
||||
#include "vma/vk_mem_alloc.h"
|
||||
#include "render/render_buffer.h"
|
||||
#include <variant>
|
||||
namespace api {
|
||||
struct BufferDesc;
|
||||
}
|
||||
namespace vkn {
|
||||
class Device;
|
||||
class Queue;
|
||||
class VulkanContext;
|
||||
using api::DynamicBuffer;
|
||||
extern pmr::FrameAllocatorPool vkCpuBufferPool;
|
||||
inline pmr::FrameAllocatorPool* BufferPool(){
|
||||
return &vkCpuBufferPool;
|
||||
}
|
||||
|
||||
enum class TransferBufferType : uint8_t{
|
||||
Transfer,
|
||||
Graphics
|
||||
};
|
||||
struct Buffer {
|
||||
VkBuffer buffer = VK_NULL_HANDLE;
|
||||
VmaAllocation allocation = VK_NULL_HANDLE;
|
||||
@ -29,26 +34,57 @@ namespace vkn {
|
||||
void** ppCpuData;
|
||||
uint32_t size;
|
||||
VkBufferUsageFlags usage;
|
||||
VkMemoryPropertyFlags momoryFlags;
|
||||
VmaMemoryUsage memoryUsage;
|
||||
};
|
||||
struct BufferCommand {
|
||||
using Command = std::variant<BufferUpload, BufferCreator>;
|
||||
Command cmd;
|
||||
BufferCommand(const BufferUpload& cmd) : cmd(cmd){}
|
||||
BufferCommand(const BufferCreator& cmd) : cmd(cmd) {}
|
||||
};
|
||||
struct ImageCreator {
|
||||
VkImageCreateInfo imageInfo;
|
||||
VkImage* image;
|
||||
};
|
||||
struct ImageUpdator {
|
||||
VkImage image;
|
||||
uint32_t size;
|
||||
uint32_t mipLevel;
|
||||
TextureUpdateArgs args;
|
||||
};
|
||||
struct SyncTransferCommand {
|
||||
uint32_t frameNumber;
|
||||
};
|
||||
struct BufferCommand {
|
||||
using Command = std::variant<BufferUpload, BufferCreator, ImageUpdator, SyncTransferCommand>;
|
||||
Command cmd;
|
||||
BufferCommand(const BufferUpload& cmd) : cmd(cmd) {}
|
||||
BufferCommand(const BufferCreator& cmd) : cmd(cmd) {}
|
||||
BufferCommand(const ImageUpdator& cmd) : cmd(cmd) {}
|
||||
BufferCommand(const SyncTransferCommand& cmd) : cmd(cmd) {}
|
||||
};
|
||||
struct DynamicBufferPool {
|
||||
TransferBufferType type;
|
||||
uint32_t commandIndex{0};
|
||||
uint32_t safeFrameNumber{0};
|
||||
VkCommandBuffer* pCommands;
|
||||
DynamicBuffer uploadBuffer;
|
||||
DynamicBufferPool(TransferBufferType type) : type(type) {}
|
||||
void CreateDynamicBuffers();
|
||||
DynamicBuffer* FindUploadBuffer(uint32_t size,uint32_t frameNumber,const void* data);
|
||||
};
|
||||
class BufferWorker : public ThreadWorker<BufferCommand, BufferWorker>{
|
||||
public:
|
||||
//pmr::vector<Buffer> mPool{BufferPool()};
|
||||
uint32_t mFrameNumber{ 0 };
|
||||
DynamicBufferPool mTransferBuffer{ TransferBufferType::Transfer };
|
||||
DynamicBufferPool mGraphicsBuffer{ TransferBufferType::Graphics };
|
||||
using ThreadWorker<BufferCommand, BufferWorker>::ThreadWorker;
|
||||
void InitCommandBuffers(uint32_t frames);
|
||||
void InitVmaAllocator(VkInstance instance);
|
||||
void TrySyncTransfer(VulkanContext& ctx);
|
||||
void Loop();
|
||||
void UploadBuffer(const BufferUpload& elem);
|
||||
void SyncTransfer(const SyncTransferCommand& elem);
|
||||
void UploadBuffer(const BufferUpload& elem, TransferBufferType type = TransferBufferType::Graphics);
|
||||
void CreateBuffer(BufferCreator& elem);
|
||||
void CreateImage(ImageCreator& elem);
|
||||
void UpdateImage(ImageUpdator& elem, TransferBufferType type = TransferBufferType::Graphics);
|
||||
|
||||
bool BeginDynamicCommand(DynamicBufferPool*& poolRef, CommandBuffer& cmd, bool isTransfer);
|
||||
void EndDynamicCommand(DynamicBufferPool* poolRef, CommandBuffer& cmd, bool isTransfer);
|
||||
};
|
||||
};
|
||||
|
||||
@ -12,9 +12,6 @@ namespace vkn {
|
||||
void InvokeBuffer(const commandFn& fn, const Element& callback);
|
||||
void Buffer(CommandBuffer& cmd, const commandFn& fn, const Element& callback);
|
||||
void Flush();
|
||||
void ImmediatelyExecute(const commandFn& fn, const Element& callback) {
|
||||
Buffer(mImmediateExeCmd, fn , callback);
|
||||
}
|
||||
bool Present(VkPresentInfoKHR& presentInfo);
|
||||
void Loop();
|
||||
void SyncInvoke(const Element& fn);
|
||||
|
||||
@ -12,8 +12,6 @@ namespace vkn {
|
||||
Device& mDevice;
|
||||
Queue& mQueue;
|
||||
CommandPool mCommandPool;
|
||||
CommandBuffer mImmediateExeCmd;
|
||||
VkFence mImmediateFence;
|
||||
public:
|
||||
ThreadWorker(Name name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags)
|
||||
: zstd::ThreadWorker<value_type, Worker>(64)
|
||||
@ -21,8 +19,6 @@ namespace vkn {
|
||||
, mDevice(device)
|
||||
, mQueue(queue)
|
||||
, mCommandPool(device, queueFlags, queue.QueueFamilyIndex())
|
||||
, mImmediateExeCmd(mCommandPool.AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY))
|
||||
, mImmediateFence(device.CreateFence(VK_FENCE_CREATE_SIGNALED_BIT))
|
||||
{}
|
||||
CommandPool& GetCommandPool() {
|
||||
return mCommandPool;
|
||||
|
||||
@ -30,6 +30,7 @@ namespace vkn {
|
||||
using api::ShaderDescriptorType;
|
||||
using api::BufferUsage;
|
||||
using api::MaterialInfo;
|
||||
using api::TextureUpdateArgs;
|
||||
|
||||
constexpr string_view VulkanEngineName = "vulkan";
|
||||
constexpr uint8_t MAX_SUPPORTED_RENDER_TARGET_COUNT = 8u;
|
||||
|
||||
@ -41,11 +41,14 @@ 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);
|
||||
RenderPassInfo* GetRenderPassInfo(size_t& hash, const RenderPassKey& config);
|
||||
|
||||
@ -5,6 +5,7 @@ namespace vkn {
|
||||
using api::TextureBarrier;
|
||||
using api::ShaderDescriptorType;
|
||||
using api::ShaderStage;
|
||||
using api::ResourceMemoryUsage;
|
||||
struct VkTextureTransitionDesc {
|
||||
VkAccessFlags srcAccessMask;
|
||||
VkAccessFlags dstAccessMask;
|
||||
@ -25,6 +26,9 @@ namespace vkn {
|
||||
|
||||
VkDescriptorType vkApiGetDescriptorType(ShaderDescriptorType type);
|
||||
VkShaderStageFlags vkApiGetShaderStageFlags(ShaderStage stage);
|
||||
VkBufferUsageFlagBits vkApiGetBufferUsage(BufferUsage usage);
|
||||
VkSamplerCreateInfo vkApiGetSamplerCreateInfo(TextureSampler sampler);
|
||||
|
||||
VkBufferUsageFlagBits vkApiGetBufferUsage(BufferUsage usage);
|
||||
VkMemoryPropertyFlags vkApiGetMemoryFlags(ResourceMemoryUsage usageFlags);
|
||||
VmaMemoryUsage vkApiGetMemoryUsage(ResourceMemoryUsage usageFlags);
|
||||
}
|
||||
@ -10,11 +10,11 @@ namespace vkn {
|
||||
uint32_t frames;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t framesInFlight;
|
||||
VkFormat imageFormat;
|
||||
VkColorSpaceKHR imageColorSpace;
|
||||
VkPresentModeKHR presentMode;
|
||||
VkImageUsageFlags imageUsage;
|
||||
uint32_t maxFrameInFlightCount;
|
||||
VkExtent2D EnableImageExtent2D(VkSurfaceCapabilitiesKHR& capabilities);
|
||||
static VulkanWindowArgs Default(uint32_t frames);
|
||||
};
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
namespace vkn {
|
||||
BufferWorker* Backend::TransferWorker;
|
||||
CommandWorker* Backend::RenderWorker;
|
||||
CommandWorker* Backend::PresentWorker;
|
||||
template<typename Worker>
|
||||
inline Worker* Backend::InitWorker(Name name, VkCommandPoolCreateFlags flag)
|
||||
{
|
||||
@ -28,8 +27,8 @@ namespace vkn {
|
||||
deviceCreator.AddQueue(Queue::TransferQueue, VkQueueFlagBits::VK_QUEUE_TRANSFER_BIT, 1.0);
|
||||
mDevice = new (GlobalPool()) Device(deviceCreator);
|
||||
|
||||
Backend::RenderWorker = InitWorker<CommandWorker>(Queue::RenderQueue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
|
||||
Backend::TransferWorker = InitWorker<BufferWorker>(Queue::TransferQueue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
|
||||
Backend::RenderWorker = InitWorker<CommandWorker>(Queue::RenderQueue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
|
||||
Backend::TransferWorker->InitVmaAllocator(mInstance->Ptr());
|
||||
|
||||
auto poolSizes = DescriptorPool::DefaultDescriptorPoolSize();
|
||||
|
||||
@ -1,11 +1,19 @@
|
||||
#define VMA_IMPLEMENTATION
|
||||
#include "vkn/backend.h"
|
||||
#include "vkn/thread/command_worker.h"
|
||||
#include "vkn/thread/buffer_worker.h"
|
||||
#include "vkn/wrapper/queue.h"
|
||||
#include "vkn/wrapper/device.h"
|
||||
#include "vkn/vulkan_api_help.h"
|
||||
#include "vkn/vulkan_context.h"
|
||||
#include "meta/variant.h"
|
||||
#include "zlog.h"
|
||||
#define MAX_TRANSFER_SYNC_FENCES 11
|
||||
#define SYNC_TRANSFER_INTERVAL_MS 100 // 每秒同步一次
|
||||
#define DYNAMIC_TEX_SIZE 128 * 1024
|
||||
namespace vkn {
|
||||
static VkFence fenceList[MAX_TRANSFER_SYNC_FENCES - 1];
|
||||
static VkCommandBuffer* commandList;
|
||||
static pmr::FrameAllocatorPool vkCpuBufferPool;
|
||||
static VmaAllocator vmaAllocator;
|
||||
void BufferWorker::InitVmaAllocator(VkInstance instance)
|
||||
@ -25,40 +33,84 @@ namespace vkn {
|
||||
vmaInfo.pVulkanFunctions = &vmaVkFunctions;
|
||||
|
||||
vmaCreateAllocator(&vmaInfo, &vmaAllocator);
|
||||
mTransferBuffer.CreateDynamicBuffers();
|
||||
mGraphicsBuffer.CreateDynamicBuffers();
|
||||
}
|
||||
void BufferWorker::InitCommandBuffers(uint32_t frames)
|
||||
{
|
||||
commandList = (VkCommandBuffer*)xmalloc(MAX_TRANSFER_SYNC_FENCES * (frames + 1) * sizeof(VkCommandBuffer));
|
||||
for (uint32_t i = 0; i <= frames; i++) {
|
||||
for (uint32_t j = 0; j < MAX_TRANSFER_SYNC_FENCES - 1; j++) {
|
||||
uint32_t k = j + (MAX_TRANSFER_SYNC_FENCES - 1) * i;
|
||||
if (i == frames) {
|
||||
fenceList[j] = mDevice.CreateFence(VK_FENCE_CREATE_SIGNALED_BIT);
|
||||
commandList[k] = GetCommandPool().AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
|
||||
}
|
||||
else {
|
||||
commandList[k] = Backend::RenderWorker->GetCommandPool().AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
|
||||
}
|
||||
}
|
||||
}
|
||||
vkResetFences(mDevice.Ptr(), MAX_TRANSFER_SYNC_FENCES - 1, fenceList);
|
||||
mTransferBuffer.pCommands = commandList + (MAX_TRANSFER_SYNC_FENCES - 1) * frames;
|
||||
mGraphicsBuffer.pCommands = commandList;
|
||||
mFrameNumber = frames;
|
||||
}
|
||||
void BufferWorker::TrySyncTransfer(VulkanContext& ctx)
|
||||
{
|
||||
uint32_t frameNumber = ctx.frameNumber++;
|
||||
if (frameNumber - mTransferBuffer.safeFrameNumber > SYNC_TRANSFER_INTERVAL_MS && mTransferBuffer.commandIndex < MAX_TRANSFER_SYNC_FENCES) {
|
||||
mTransferBuffer.commandIndex += MAX_TRANSFER_SYNC_FENCES;
|
||||
Invoke(SyncTransferCommand{ frameNumber });
|
||||
}
|
||||
mFrameNumber = frameNumber;//保守一点,慢一帧
|
||||
mGraphicsBuffer.commandIndex = 0;
|
||||
mGraphicsBuffer.pCommands = commandList + (MAX_TRANSFER_SYNC_FENCES - 1) * ctx.frame;
|
||||
mGraphicsBuffer.safeFrameNumber = ctx.frameNumber - ctx.frameCount;
|
||||
}
|
||||
void BufferWorker::SyncTransfer(const SyncTransferCommand& elem)
|
||||
{
|
||||
DynamicBufferPool& bufferPoolRef = mTransferBuffer;
|
||||
uint32_t index = bufferPoolRef.commandIndex % (MAX_TRANSFER_SYNC_FENCES);
|
||||
if (index) { //没有提交任务时,不需要等待
|
||||
vkWaitForFences(mDevice.Ptr(), index - 1, fenceList, VK_TRUE, UINT64_MAX);
|
||||
vkResetFences(mDevice.Ptr(), index - 1, fenceList);
|
||||
}
|
||||
bufferPoolRef.safeFrameNumber = elem.frameNumber;
|
||||
bufferPoolRef.commandIndex = 0;
|
||||
}
|
||||
void BufferWorker::Loop()
|
||||
{
|
||||
while (true) {
|
||||
Element elem = mChannel.acquire();
|
||||
std::visit(meta::overloaded{
|
||||
[&](BufferUpload& cmd) { UploadBuffer(cmd); },
|
||||
[&](BufferUpload& cmd) { UploadBuffer(cmd, TransferBufferType::Transfer); },
|
||||
[&](BufferCreator& cmd) { CreateBuffer(cmd); },
|
||||
[&](ImageUpdator& cmd) { UpdateImage(cmd); },
|
||||
[&](SyncTransferCommand& cmd) { SyncTransfer(cmd); },
|
||||
}, elem.cmd);
|
||||
}
|
||||
}
|
||||
void BufferWorker::UploadBuffer(const BufferUpload& elem)
|
||||
void BufferWorker::UploadBuffer(const BufferUpload& elem, TransferBufferType type)
|
||||
{
|
||||
mImmediateExeCmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
||||
bool isTransfer = type == TransferBufferType::Transfer;
|
||||
DynamicBufferPool* pPoolRef;
|
||||
CommandBuffer command;
|
||||
if (!BeginDynamicCommand(pPoolRef, command, isTransfer)) {
|
||||
Invoke(elem);
|
||||
return;
|
||||
}
|
||||
// 将数据复制到 Staging Buffer
|
||||
DynamicBuffer* uploadBuffer = pPoolRef->FindUploadBuffer(elem.size, mFrameNumber + 1,elem.pCpuData);
|
||||
|
||||
VmaAllocationCreateInfo allocationInfo = {};
|
||||
allocationInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
|
||||
|
||||
VkBufferCreateInfo bufferInfo = {};
|
||||
bufferInfo.size = elem.size;
|
||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
|
||||
VmaAllocation stagingAllocation;
|
||||
|
||||
VmaAllocationCreateInfo allocationInfo = {};
|
||||
allocationInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
|
||||
|
||||
VkBuffer stagingBuffer;
|
||||
vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocationInfo, &stagingBuffer, &stagingAllocation, nullptr);
|
||||
|
||||
// 将数据复制到 Staging Buffer
|
||||
void* data;
|
||||
vmaMapMemory(vmaAllocator, stagingAllocation, &data);
|
||||
memcpy(data, elem.pCpuData, elem.size);
|
||||
vmaUnmapMemory(vmaAllocator, stagingAllocation);
|
||||
|
||||
// 创建 GPU Buffer, GPU内部缓冲区,访问速度非常快
|
||||
VkBuffer& gpuBuffer = *elem.pBuffer;
|
||||
bufferInfo.usage = elem.usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
@ -68,12 +120,10 @@ namespace vkn {
|
||||
// 复制数据
|
||||
VkBufferCopy copyRegion = {};
|
||||
copyRegion.size = elem.size;
|
||||
vkCmdCopyBuffer(mImmediateExeCmd.Ptr(), stagingBuffer, gpuBuffer, 1, ©Region);
|
||||
mImmediateExeCmd.EndRecord();
|
||||
vkResetFences(mDevice.Ptr(), 1, &mImmediateFence);
|
||||
mImmediateExeCmd.Submit(mQueue.Ptr(), mImmediateFence);
|
||||
vkWaitForFences(mDevice.Ptr(), 1, &mImmediateFence, VK_TRUE, UINT64_MAX);
|
||||
vmaDestroyBuffer(vmaAllocator, stagingBuffer, stagingAllocation);
|
||||
copyRegion.srcOffset = uploadBuffer->drawPos;
|
||||
vkCmdCopyBuffer(command.Ptr(), (VkBuffer)uploadBuffer->currentPage->pBuffer, gpuBuffer, 1, ©Region);
|
||||
|
||||
EndDynamicCommand(pPoolRef, command, isTransfer);
|
||||
}
|
||||
void BufferWorker::CreateBuffer(BufferCreator& elem)
|
||||
{
|
||||
@ -84,6 +134,7 @@ namespace vkn {
|
||||
|
||||
VmaAllocationCreateInfo allocationInfo = {};
|
||||
allocationInfo.usage = elem.memoryUsage;
|
||||
allocationInfo.requiredFlags = elem.momoryFlags;
|
||||
if (elem.ppCpuData)
|
||||
allocationInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
|
||||
vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocationInfo, elem.pBuffer, elem.pAllocation, nullptr);
|
||||
@ -99,4 +150,69 @@ namespace vkn {
|
||||
VmaAllocation allocation;
|
||||
VkResult result = vmaCreateImage(vmaAllocator, &elem.imageInfo, &allocCreateInfo, elem.image, &allocation, nullptr);
|
||||
}
|
||||
void BufferWorker::UpdateImage(ImageUpdator& elem, TransferBufferType type)
|
||||
{
|
||||
bool isTransfer = type == TransferBufferType::Transfer;
|
||||
DynamicBufferPool* pPoolRef;
|
||||
CommandBuffer command;
|
||||
if (!BeginDynamicCommand(pPoolRef, command, isTransfer)) {
|
||||
Invoke(elem);
|
||||
return;
|
||||
}
|
||||
TextureUpdateArgs args = elem.args;
|
||||
// 将数据复制到 Staging Buffer
|
||||
DynamicBuffer* uploadBuffer = pPoolRef->FindUploadBuffer(elem.size, mFrameNumber + 1, args.data);
|
||||
|
||||
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.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, ®ion);
|
||||
EndDynamicCommand(pPoolRef, command, isTransfer);
|
||||
}
|
||||
bool BufferWorker::BeginDynamicCommand(DynamicBufferPool*& pPoolRef, CommandBuffer& command, bool isTransfer)
|
||||
{
|
||||
pPoolRef = isTransfer ? &mTransferBuffer : &mGraphicsBuffer;
|
||||
if (pPoolRef->commandIndex >= MAX_TRANSFER_SYNC_FENCES) {
|
||||
return false;
|
||||
}
|
||||
command = pPoolRef->pCommands[pPoolRef->commandIndex];
|
||||
command.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
||||
return true;
|
||||
}
|
||||
void BufferWorker::EndDynamicCommand(DynamicBufferPool* pPoolRef, CommandBuffer& command, bool isTransfer)
|
||||
{
|
||||
command.EndRecord();
|
||||
pPoolRef->commandIndex++;
|
||||
if (isTransfer) {
|
||||
command.Submit(mQueue.Ptr(), fenceList[pPoolRef->commandIndex - 1]);
|
||||
if (pPoolRef->commandIndex >= MAX_TRANSFER_SYNC_FENCES) {
|
||||
SyncTransfer(SyncTransferCommand{ mFrameNumber });
|
||||
}
|
||||
return;
|
||||
}
|
||||
command.Submit(Backend::RenderWorker->GetQueue().Ptr(), nullptr);
|
||||
}
|
||||
void DynamicBufferPool::CreateDynamicBuffers()
|
||||
{
|
||||
uploadBuffer.InitBuffer(DYNAMIC_TEX_SIZE, BufferUsage::TRANSFER_SRC,
|
||||
ResourceMemoryUsage::HOST_VISIBLE | ResourceMemoryUsage::HOST_COHERENT);
|
||||
}
|
||||
DynamicBuffer* DynamicBufferPool::FindUploadBuffer(uint32_t size, uint32_t frameNumber, const void* data)
|
||||
{
|
||||
// 将数据复制到 Staging Buffer
|
||||
void* pMappingAddr = uploadBuffer.MapBuffer(meta_align_size(size, 4), frameNumber, safeFrameNumber);
|
||||
if (data) {
|
||||
memcpy(pMappingAddr, data, size);
|
||||
}
|
||||
return &uploadBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ namespace vkn {
|
||||
}
|
||||
void VulkanAPI::Init()
|
||||
{
|
||||
|
||||
Backend::TransferWorker->InitCommandBuffers(context.frameCount);
|
||||
}
|
||||
void VulkanAPI::Shutdown()
|
||||
{
|
||||
@ -267,7 +267,15 @@ namespace vkn {
|
||||
}
|
||||
void VulkanAPI::CreateBuffer(BufferDesc& desc)
|
||||
{
|
||||
|
||||
BufferCreator creator{};
|
||||
creator.size = desc.size;
|
||||
creator.pBuffer = (VkBuffer*)&desc.buffer;
|
||||
creator.pAllocation =(VmaAllocation*) &desc.pAllocation;
|
||||
creator.ppCpuData = &desc.pMappingAddr;
|
||||
creator.memoryUsage = vkApiGetMemoryUsage(desc.memoryUsage);
|
||||
creator.momoryFlags = vkApiGetMemoryFlags(desc.memoryUsage);
|
||||
creator.usage = vkApiGetBufferUsage(desc.usage);
|
||||
Backend::TransferWorker->CreateBuffer(creator);
|
||||
}
|
||||
void VulkanAPI::CreateTexture(TextureDesc& desc)
|
||||
{
|
||||
@ -332,6 +340,31 @@ 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;
|
||||
@ -343,6 +376,7 @@ namespace vkn {
|
||||
{
|
||||
VulkanContext& ctx = *(VulkanContext*)&context;
|
||||
window.Present(ctx);
|
||||
Backend::TransferWorker->TrySyncTransfer(ctx);
|
||||
}
|
||||
void VulkanAPI::ExecuteResourceBarriers(const ResourceBarrierDesc& desc) {
|
||||
VulkanContext& ctx = *(VulkanContext*)&context;
|
||||
|
||||
@ -256,19 +256,6 @@ namespace vkn {
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
VkBufferUsageFlagBits vkApiGetBufferUsage(BufferUsage usage)
|
||||
{
|
||||
if (any(usage & BufferUsage::VERTEX)) {
|
||||
return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||
}
|
||||
if (any(usage & BufferUsage::UNIFORM)) {
|
||||
return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||
}
|
||||
if (any(usage & BufferUsage::SHADER_STORAGE)) {
|
||||
return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
using api::SamplerWrapMode;
|
||||
using api::SamplerMinFilter;
|
||||
using api::SamplerMagFilter;
|
||||
@ -380,4 +367,52 @@ namespace vkn {
|
||||
};
|
||||
return samplerInfo;
|
||||
}
|
||||
VkBufferUsageFlagBits vkApiGetBufferUsage(BufferUsage usage)
|
||||
{
|
||||
if (any(usage & BufferUsage::VERTEX)) {
|
||||
return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||
}
|
||||
if (any(usage & BufferUsage::UNIFORM)) {
|
||||
return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||
}
|
||||
if (any(usage & BufferUsage::SHADER_STORAGE)) {
|
||||
return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
}
|
||||
if (any(usage & BufferUsage::TRANSFER_SRC)) {
|
||||
return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
VkMemoryPropertyFlags vkApiGetMemoryFlags(ResourceMemoryUsage usageFlags) {
|
||||
VkMemoryPropertyFlags flags = 0;
|
||||
if (any(usageFlags & ResourceMemoryUsage::HOST_VISIBLE)) {
|
||||
flags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
||||
}
|
||||
if (any(usageFlags & ResourceMemoryUsage::GPU_ONLY)) {
|
||||
flags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||
}
|
||||
if (any(usageFlags & ResourceMemoryUsage::HOST_COHERENT)) {
|
||||
flags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
||||
}
|
||||
if (any(usageFlags & ResourceMemoryUsage::LAZY_ALLOCATED)) {
|
||||
flags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
VmaMemoryUsage vkApiGetMemoryUsage(ResourceMemoryUsage usageFlags) {
|
||||
if (any(usageFlags & ResourceMemoryUsage::GPU_ONLY)) {
|
||||
return VMA_MEMORY_USAGE_GPU_ONLY;
|
||||
}
|
||||
if (any(usageFlags & ResourceMemoryUsage::CPU_ONLY)) {
|
||||
return VMA_MEMORY_USAGE_CPU_ONLY;
|
||||
}
|
||||
if (any(usageFlags & ResourceMemoryUsage::CPU_TO_GPU)) {
|
||||
return VMA_MEMORY_USAGE_CPU_TO_GPU;
|
||||
}
|
||||
if (any(usageFlags & ResourceMemoryUsage::GPU_TO_CPU)) {
|
||||
return VMA_MEMORY_USAGE_GPU_TO_CPU;
|
||||
}
|
||||
return VMA_MEMORY_USAGE_UNKNOWN; // 默认
|
||||
}
|
||||
}
|
||||
@ -22,7 +22,8 @@ namespace vkn {
|
||||
args.width = mWidth;
|
||||
args.height = mHeight;
|
||||
mSwapchain = new (GlobalPool()) VulkanSwapchain(backend.GetDevice(), surface, args);
|
||||
api->context.frameCount = args.frames;
|
||||
api->context.frameCount = args.framesInFlight;
|
||||
api->context.frameNumber = args.framesInFlight;
|
||||
api->context.surface = mSwapchain->mSurfaces[0];
|
||||
api->graph.InitSurface(mSwapchain->mSurfaces.data(), mSwapchain->mSurfaces.size());
|
||||
return true;
|
||||
@ -57,7 +58,7 @@ namespace vkn {
|
||||
if (result != VK_SUCCESS) {
|
||||
zlog::error("Failed to create swap chain.");
|
||||
}
|
||||
mFrames = args.frames;
|
||||
mFrames = args.framesInFlight;
|
||||
pmr::vector<VkImage> swapchain_images{ FramePool() };
|
||||
uint32_t imageCount = 0;
|
||||
vkGetSwapchainImagesKHR(device.Ptr(), mPtr, &imageCount, nullptr);
|
||||
@ -138,11 +139,11 @@ namespace vkn {
|
||||
{
|
||||
return {
|
||||
.frames = frames,
|
||||
.framesInFlight = 2,
|
||||
.imageFormat = VK_FORMAT_B8G8R8A8_SRGB,
|
||||
.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
|
||||
.presentMode = VK_PRESENT_MODE_MAILBOX_KHR,
|
||||
.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
.maxFrameInFlightCount = 2
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,16 @@
|
||||
#include "editor/editor.h"
|
||||
#include "editor/window/editor_main_window.h"
|
||||
#include "ui/ui_render_device.h"
|
||||
#include "event/event_system.h"
|
||||
#include "os/file_manager.h"
|
||||
#include <NoesisPCH.h>
|
||||
namespace api {
|
||||
using namespace Noesis;
|
||||
Ptr<IView> mView;
|
||||
void EditorModule::OnLoad(int argc, char** argv)
|
||||
{
|
||||
|
||||
PackagePath editor_noesis{"/engine/assets/noesis"};
|
||||
FileManager::Ptr()->Mount("editor_noesis", editor_noesis.RealPath().c_str());
|
||||
}
|
||||
|
||||
void EditorModule::OnUnload()
|
||||
@ -10,6 +18,17 @@ namespace api {
|
||||
}
|
||||
void EditorModule::Initialize(void)
|
||||
{
|
||||
|
||||
Ptr<FrameworkElement> xaml = GUI::LoadXaml<FrameworkElement>("/editor_noesis/Menu.xaml");
|
||||
mView = GUI::CreateView(xaml);
|
||||
mView->SetFlags(RenderFlags_PPAA | RenderFlags_LCD);
|
||||
mView->SetSize(1024, 768);
|
||||
//mView->GetRenderer()->Init(UIRenderDevice::Ptr());
|
||||
EventSystem::Ptr()->BeginRenderFrame.Subscribe(mInfo.name, [](FrameGraph& graph, int32_t frame) {
|
||||
//mView->Update(0.033);
|
||||
//IRenderer* renderer = mView->GetRenderer();
|
||||
//renderer->UpdateRenderTree();
|
||||
//renderer->RenderOffscreen();
|
||||
//renderer->Render();
|
||||
});
|
||||
}
|
||||
}
|
||||
9
engine/src/editor/window/editor_main_window.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include "editor/window/editor_main_window.h"
|
||||
namespace api {
|
||||
void EditorMainWindow::InitializeComponent()
|
||||
{
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
int j = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,24 +1,28 @@
|
||||
#include "engine/api.h"
|
||||
#include "os/file_manager.h"
|
||||
#include "ui/ui_render_device.h"
|
||||
#include "xmalloc_new_delete.h"
|
||||
class ENGINE_API EngineModule : public api::IDynamicModule
|
||||
{
|
||||
public:
|
||||
void OnLoad(int argc, char** argv) override {
|
||||
namespace api {
|
||||
class ENGINE_API EngineModule : public api::IDynamicModule
|
||||
{
|
||||
public:
|
||||
void OnLoad(int argc, char** argv) override {
|
||||
#ifdef ENGINE_ROOT
|
||||
api::FileManager::Ptr()->Mount("engine", TOSTRING(ENGINE_ROOT));
|
||||
api::FileManager::Ptr()->Mount("engine", TOSTRING(ENGINE_ROOT));
|
||||
#endif
|
||||
};
|
||||
void OnUnload() override {
|
||||
};
|
||||
void InitMetaData(void) override {
|
||||
mInfo.dependencies = {
|
||||
{"app","1.0.1", "static"},
|
||||
{"core", "1.0.1", "static" },
|
||||
{"asset", "1.0.1", "static" },
|
||||
{"render", "1.0.1", "static" },
|
||||
{"ui", "1.0.1", "static" },
|
||||
new UIRenderDevice(RenderAPI::Ptr());
|
||||
};
|
||||
void OnUnload() override {
|
||||
};
|
||||
void InitMetaData(void) override {
|
||||
mInfo.dependencies = {
|
||||
{"app","1.0.1", "static"},
|
||||
{"core", "1.0.1", "static" },
|
||||
{"asset", "1.0.1", "static" },
|
||||
{"render", "1.0.1", "static" },
|
||||
{"ui", "1.0.1", "static" },
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
IMPLEMENT_DYNAMIC_MODULE(ENGINE_API, EngineModule, engine)
|
||||
IMPLEMENT_DYNAMIC_MODULE(ENGINE_API, EngineModule, engine)
|
||||
}
|
||||
@ -9,25 +9,33 @@
|
||||
#include "zlog.h"
|
||||
#include "module_manager_impl.inl"
|
||||
#include "file_manager_impl.inl"
|
||||
IMPLEMENT_STATIC_MODULE(CORE_API, api::CoreModule, core)
|
||||
#endif // !CORE_API_VAL
|
||||
|
||||
#ifndef ASSET_API_VAL
|
||||
#define ASSET_API_VAL 1
|
||||
#include "resource_system_impl.inl"
|
||||
#include "asset_visit_impl.inl"
|
||||
IMPLEMENT_STATIC_MODULE(ASSET_API, api::AssetModule, asset)
|
||||
#endif // !ASSET_API_VAL
|
||||
|
||||
#ifndef RENDER_API_VAL
|
||||
#define RENDER_API_VAL 1
|
||||
#include "renderapi_impl.inl"
|
||||
#include "window_impl.inl"
|
||||
#include "render/render_module.h"
|
||||
IMPLEMENT_STATIC_MODULE(RENDER_API, api::RenderModule, render);
|
||||
#endif // !RENDER_API_VAL
|
||||
|
||||
#ifndef APP_API_VAL
|
||||
#define APP_API_VAL 1
|
||||
#include "app_impl.inl"
|
||||
#include "event_system_impl.inl"
|
||||
IMPLEMENT_STATIC_MODULE(APP_API, api::AppModule, app)
|
||||
#endif // !APP_API_VAL
|
||||
|
||||
#include "ui/ui_module.h"
|
||||
IMPLEMENT_STATIC_MODULE(UI_API, api::UIModule, ui)
|
||||
#ifndef UI_API_VAL
|
||||
#define UI_API_VAL 1
|
||||
#include "ui_render_device_impl.inl"
|
||||
IMPLEMENT_STATIC_MODULE(UI_API, api::UIModule, ui)
|
||||
#endif // !UI_API_VAL
|
||||
|
||||
@ -12,7 +12,7 @@ target("editor")
|
||||
set_kind("shared")
|
||||
set_group("Engine")
|
||||
add_rules("engine.api")
|
||||
add_headerfiles("include/editor/**.h")
|
||||
add_headerfiles("include/editor/**.h","assets/noesis/*.xaml")
|
||||
add_includedirs("include")
|
||||
add_files("src/editor/**.cpp")
|
||||
add_deps("engine",{public = true})
|
||||
|
||||
@ -20,9 +20,6 @@ void ZWorldModule::OnLoad(int argc, char** argv)
|
||||
window->CreateRender(args);
|
||||
API->Init();
|
||||
API->context.views.push_back({});
|
||||
EventSystem::Ptr()->BeginRenderFrame.Subscribe(mInfo.name, [](FrameGraph& graph, uint32_t frame) {
|
||||
graph.AddRenderPass<DemoPass>();
|
||||
});
|
||||
}
|
||||
void ZWorldModule::InitMetaData()
|
||||
{
|
||||
@ -35,6 +32,9 @@ void ZWorldModule::InitMetaData()
|
||||
}
|
||||
void ZWorldModule::Initialize()
|
||||
{
|
||||
EventSystem::Ptr()->BeginRenderFrame.Subscribe(mInfo.name, [](FrameGraph& graph, uint32_t frame) {
|
||||
graph.AddRenderPass<DemoPass>();
|
||||
});
|
||||
}
|
||||
void ZWorldModule::OnUnload()
|
||||
{
|
||||
|
||||
@ -6,7 +6,7 @@ set_languages("cxx20")
|
||||
set_project("zengine")
|
||||
set_toolchains("clang")
|
||||
set_runtimes("MD","c++_shared")
|
||||
add_cxflags("-stdlib=libc++")
|
||||
add_cxxflags("-stdlib=libc++", "-Wno-parentheses-equality")
|
||||
add_ldflags("-stdlib=libc++")
|
||||
includes("engine")
|
||||
includes("game/*/xmake.lua")
|
||||
|
||||