update thread_worker
This commit is contained in:
parent
25664db985
commit
8b234cd835
@ -5,7 +5,7 @@ namespace refl {
|
||||
constexpr std::string_view func_signature() noexcept {
|
||||
# if defined(__clang__)
|
||||
auto sign = std::string_view{ __PRETTY_FUNCTION__ };
|
||||
return sign.substr(53, sign.size() - 54);
|
||||
return sign.substr(47, sign.size() - 47);
|
||||
# elif defined(__GNUC__)
|
||||
auto sign = std::string_view{ __PRETTY_FUNCTION__ };
|
||||
return sign.substr(62, sign.size() - 62);
|
||||
|
||||
@ -10,7 +10,7 @@ namespace refl {
|
||||
parray(): m_cls(nullptr), m_ptr(nullptr),m_count(0) {}
|
||||
template<typename C>
|
||||
requires std::is_base_of_v<T, C>
|
||||
parray(std::vector<C>& vec) : m_cls(&TypeInfo<C>::StaticClass), m_ptr(nullptr){
|
||||
parray(std::vector<C>& vec) : m_cls(type_info<C>()), m_ptr(nullptr){
|
||||
m_count = vec.size();
|
||||
if (m_count > 0) {
|
||||
C* ptr = new C[m_count];
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#include <semaphore>
|
||||
#include <concepts>
|
||||
namespace zstd {
|
||||
template<std::move_constructible T>
|
||||
template<typename T>
|
||||
class channel {
|
||||
protected:
|
||||
int m_tail;
|
||||
|
||||
29
engine/modules/engine/zlib/include/std/thread.h
Normal file
29
engine/modules/engine/zlib/include/std/thread.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "channel.h"
|
||||
#include <thread>
|
||||
namespace zstd{
|
||||
template<typename value_type, typename Worker>
|
||||
class ThreadWorker {
|
||||
public:
|
||||
using Element = value_type;
|
||||
std::thread mThread;
|
||||
channel<Element> mChannel;
|
||||
void WorkLoop() {
|
||||
mThread.detach();
|
||||
}
|
||||
void Loop() {
|
||||
Worker* worker = dynamic_cast<Worker*>(this);
|
||||
worker->Loop();
|
||||
}
|
||||
public:
|
||||
ThreadWorker() : ThreadWorker(64) {}
|
||||
ThreadWorker(int buffer) : mChannel(buffer)
|
||||
{
|
||||
mThread = std::thread(&ThreadWorker::WorkLoop, this);
|
||||
}
|
||||
|
||||
void Invoke(const Element& elem) {
|
||||
mChannel.release(elem);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "thread/worker.h"
|
||||
#include "vkn/type.h"
|
||||
namespace vkn {
|
||||
class Device;
|
||||
class Instance;
|
||||
@ -7,16 +7,15 @@ namespace vkn {
|
||||
protected:
|
||||
Instance* mInstance;
|
||||
Device* mDevice;
|
||||
table<Name, CommandWorker*> mWorkerMap;
|
||||
public:
|
||||
Backend(string_view appName);
|
||||
~Backend();
|
||||
void InitWorker(Name name, VkCommandPoolCreateFlags flag);
|
||||
CommandWorker* GetWorker(Name name);
|
||||
template<typename Worker>
|
||||
Worker* InitWorker(Name name, VkCommandPoolCreateFlags flag);
|
||||
|
||||
public:
|
||||
static CommandWorker* TransferWorker;
|
||||
static CommandWorker* RenderWorker;
|
||||
static CommandWorker* PresentWorker;
|
||||
static struct BufferWorker* TransferWorker;
|
||||
static struct CommandWorker* RenderWorker;
|
||||
static struct CommandWorker* PresentWorker;
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "worker.h"
|
||||
#include "vkn/wrapper/buffer.h"
|
||||
namespace vkn {
|
||||
class Device;
|
||||
class Queue;
|
||||
struct Buffer;
|
||||
class BufferWorker : public ThreadWorker<Buffer, BufferWorker>{
|
||||
public:
|
||||
using ThreadWorker<Buffer, BufferWorker>::ThreadWorker;
|
||||
void InitVmaAllocator(VkInstance instance);
|
||||
void Loop();
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "worker.h"
|
||||
#include <semaphore>
|
||||
namespace vkn {
|
||||
class Device;
|
||||
class Queue;
|
||||
class CommandWorker : public ThreadWorker<voidFn, CommandWorker> {
|
||||
protected:
|
||||
std::binary_semaphore mSemaphore{0};
|
||||
public:
|
||||
using ThreadWorker<voidFn, CommandWorker>::ThreadWorker;
|
||||
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);
|
||||
};
|
||||
};
|
||||
@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
#include <thread>
|
||||
#include "vkn/type.h"
|
||||
#include <semaphore>
|
||||
namespace vkn {
|
||||
class CommandThreadWorker {
|
||||
protected:
|
||||
std::thread mThread;
|
||||
Name mName;
|
||||
channel<voidFn> mChannel;
|
||||
std::binary_semaphore mSemaphore;
|
||||
protected:
|
||||
void workloop();
|
||||
public:
|
||||
CommandThreadWorker(Name name, int buffer);
|
||||
~CommandThreadWorker();
|
||||
|
||||
void Invoke(const voidFn& fn);
|
||||
void SyncInvoke(const voidFn& fn);
|
||||
};
|
||||
};
|
||||
@ -1,32 +1,31 @@
|
||||
#pragma once
|
||||
#include "std/thread.h"
|
||||
#include "vkn/wrapper/commandpool.h"
|
||||
#include "thread_worker.h"
|
||||
#include "vkn/wrapper/queue.h"
|
||||
namespace vkn {
|
||||
class Device;
|
||||
class Queue;
|
||||
class CommandWorker {
|
||||
using zstd::channel;
|
||||
template<typename value_type, typename Worker>
|
||||
class ThreadWorker : public zstd::ThreadWorker<value_type, Worker> {
|
||||
protected:
|
||||
Name mName;
|
||||
Device& mDevice;
|
||||
Queue& mQueue;
|
||||
Name mName;
|
||||
CommandThreadWorker mWork;
|
||||
CommandPool mCommandPool;
|
||||
CommandBuffer mImmediateExeCmd;
|
||||
public:
|
||||
CommandWorker(Name name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags);
|
||||
ThreadWorker(Name name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags)
|
||||
: zstd::ThreadWorker<value_type, Worker>(64)
|
||||
, mName(name)
|
||||
, mDevice(device)
|
||||
, mQueue(queue)
|
||||
, mCommandPool(device, queueFlags, queue.QueueFamilyIndex())
|
||||
, mImmediateExeCmd(mCommandPool.AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY))
|
||||
{}
|
||||
CommandPool& GetCommandPool() {
|
||||
return mCommandPool;
|
||||
}
|
||||
Queue& GetQueue() {
|
||||
return mQueue;
|
||||
}
|
||||
void Invoke(const voidFn& fn);
|
||||
void InvokeBuffer(const commandFn& fn, const voidFn& callback);
|
||||
void Buffer(CommandBuffer& cmd, const commandFn& fn, const voidFn& callback);
|
||||
void Flush();
|
||||
void ImmediatelyExecute(const commandFn& fn, const voidFn callback) {
|
||||
Buffer(mImmediateExeCmd, fn , callback);
|
||||
}
|
||||
bool Present(VkPresentInfoKHR& presentInfo);
|
||||
};
|
||||
};
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#include "std/channel.h"
|
||||
#include "pmr/frame_allocator.h"
|
||||
#include "pmr/name.h"
|
||||
#include <Windows.h>
|
||||
@ -11,9 +10,8 @@ namespace vkn {
|
||||
using pmr::Name;
|
||||
using pmr::table;
|
||||
using std::string_view;
|
||||
using zstd::channel;
|
||||
inline constexpr string_view VulkanEngineName = "vulkan";
|
||||
class CommandBuffer;
|
||||
using voidFn = std::function<void()>;
|
||||
using commandFn = std::function<void(CommandBuffer& cmd)>;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
#pragma once
|
||||
#include "type.h"
|
||||
#include "asset/res/guid.h"
|
||||
#include "render/renderapi.h"
|
||||
#include "backend.h"
|
||||
namespace vkn {
|
||||
class Backend;
|
||||
class VulkanWindow;
|
||||
struct MeshVAO;
|
||||
using api::Guid;
|
||||
using api::Mesh;
|
||||
using api::Shader;
|
||||
class VULKAN_API VulkanAPI : public api::RenderAPI {
|
||||
private:
|
||||
VulkanWindow& window;
|
||||
Backend backend;
|
||||
table<Guid, MeshVAO> MeshTable;
|
||||
public:
|
||||
VulkanAPI();
|
||||
|
||||
|
||||
18
engine/modules/render/vulkan/include/vkn/wrapper/buffer.h
Normal file
18
engine/modules/render/vulkan/include/vkn/wrapper/buffer.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "vkn/type.h"
|
||||
namespace vkn {
|
||||
struct MeshVAO
|
||||
{
|
||||
uint32_t indexCount = 0; // 索引数量
|
||||
VkBuffer indexBuffer = VK_NULL_HANDLE;
|
||||
uint32_t vertexCount = 0; // 顶点数量
|
||||
VkBuffer vertexBuffer = VK_NULL_HANDLE;
|
||||
bool inUse = false;
|
||||
};
|
||||
struct Buffer {
|
||||
VkBuffer* ppBuffer;
|
||||
void* pCpuData;
|
||||
VkBufferUsageFlags usage;
|
||||
uint32_t size;
|
||||
};
|
||||
}
|
||||
@ -4,11 +4,19 @@
|
||||
#include "vkn/wrapper/instance.h"
|
||||
#include "vkn/wrapper/instance_create.h"
|
||||
#include "vkn/wrapper/queue.h"
|
||||
#include "vkn/thread/buffer_worker.h"
|
||||
#include "vkn/thread/command_worker.h"
|
||||
namespace vkn {
|
||||
CommandWorker* Backend::TransferWorker;
|
||||
BufferWorker* Backend::TransferWorker;
|
||||
CommandWorker* Backend::RenderWorker;
|
||||
CommandWorker* Backend::PresentWorker;
|
||||
Backend::Backend(string_view appName) : mWorkerMap(GlobalPool())
|
||||
template<typename Worker>
|
||||
inline Worker* Backend::InitWorker(Name name, VkCommandPoolCreateFlags flag)
|
||||
{
|
||||
auto queue = mDevice->GetQueue(name);
|
||||
return new Worker(name, *mDevice, *queue, flag);
|
||||
}
|
||||
Backend::Backend(string_view appName)
|
||||
{
|
||||
InstanceCreator instanceCreator{};
|
||||
mInstance = new (GlobalPool()) Instance(instanceCreator);
|
||||
@ -21,33 +29,14 @@ namespace vkn {
|
||||
deviceCreator.AddQueue(Queue::PresentQueue, VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0);
|
||||
mDevice = new (GlobalPool()) Device(deviceCreator);
|
||||
|
||||
InitWorker(Queue::TransferQueue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
|
||||
InitWorker(Queue::RenderQueue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
|
||||
InitWorker(Queue::ComputeQueue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
|
||||
InitWorker(Queue::PresentQueue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
|
||||
|
||||
Backend::TransferWorker = GetWorker(Queue::TransferQueue);
|
||||
Backend::RenderWorker = GetWorker(Queue::RenderQueue);
|
||||
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::PresentWorker = InitWorker<CommandWorker>(Queue::ComputeQueue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
|
||||
Backend::TransferWorker->InitVmaAllocator(mInstance->Ptr());
|
||||
}
|
||||
Backend::~Backend()
|
||||
{
|
||||
mInstance->~Instance();
|
||||
mDevice->~Device();
|
||||
}
|
||||
void Backend::InitWorker(Name name, VkCommandPoolCreateFlags flag)
|
||||
{
|
||||
auto queue = mDevice->GetQueue(name);
|
||||
if (queue) {
|
||||
auto worker = new CommandWorker(name, *mDevice, *queue, flag);
|
||||
mWorkerMap.emplace(name, worker);
|
||||
}
|
||||
}
|
||||
CommandWorker* Backend::GetWorker(Name name)
|
||||
{
|
||||
auto it = mWorkerMap.find(name);
|
||||
if (it != mWorkerMap.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
63
engine/modules/render/vulkan/src/thread/buffer_worker.cpp
Normal file
63
engine/modules/render/vulkan/src/thread/buffer_worker.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include "vkn/thread/buffer_worker.h"
|
||||
#include "vkn/wrapper/queue.h"
|
||||
#include "vkn/wrapper/device.h"
|
||||
#include "vma/vk_mem_alloc.h"
|
||||
#include "zlog.h"
|
||||
namespace vkn {
|
||||
static VmaAllocator vmaAllocator;
|
||||
void BufferWorker::InitVmaAllocator(VkInstance instance)
|
||||
{
|
||||
// 因为用volk库手动加载所有Vulkan函数了,所以这里要给VMA传递获取函数地址的方法,让VMA可以正确获取Vulkan函数
|
||||
VmaVulkanFunctions vmaVkFunctions = {};
|
||||
vmaVkFunctions.vkGetInstanceProcAddr = vkGetInstanceProcAddr;
|
||||
vmaVkFunctions.vkGetDeviceProcAddr = vkGetDeviceProcAddr;
|
||||
|
||||
VmaAllocatorCreateInfo vmaInfo = {};
|
||||
vmaInfo.vulkanApiVersion = VK_HEADER_VERSION_COMPLETE;
|
||||
vmaInfo.instance = instance;
|
||||
vmaInfo.physicalDevice = mDevice.GetPhysical();
|
||||
vmaInfo.device = mDevice.Ptr();
|
||||
vmaInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
|
||||
// 如果不手动加载Vulkan函数,这里可以填NULL
|
||||
vmaInfo.pVulkanFunctions = &vmaVkFunctions;
|
||||
|
||||
vmaCreateAllocator(&vmaInfo, &vmaAllocator);
|
||||
}
|
||||
void BufferWorker::Loop()
|
||||
{
|
||||
while (true) {
|
||||
Element elem = mChannel.acquire();
|
||||
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.ppBuffer;
|
||||
VmaAllocation gpuBufferAllocation;
|
||||
bufferInfo.usage = elem.usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
allocationInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||
vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocationInfo, &gpuBuffer, &gpuBufferAllocation, nullptr);
|
||||
|
||||
// 复制数据
|
||||
VkBufferCopy copyRegion = {};
|
||||
copyRegion.size = elem.size;
|
||||
vkCmdCopyBuffer(mImmediateExeCmd.Ptr(), stagingBuffer, gpuBuffer, 1, ©Region);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,30 +1,15 @@
|
||||
#include "vkn/thread/worker.h"
|
||||
#include "vkn/wrapper/queue.h"
|
||||
#include "vkn/thread/command_worker.h"
|
||||
#include "vkn/wrapper/device.h"
|
||||
namespace vkn {
|
||||
CommandWorker::CommandWorker(Name name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags)
|
||||
:mName(name)
|
||||
,mDevice(device)
|
||||
,mQueue(queue)
|
||||
,mCommandPool(device, queueFlags, queue.QueueFamilyIndex())
|
||||
,mWork(name, 64)
|
||||
,mImmediateExeCmd(mCommandPool.AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY))
|
||||
void CommandWorker::InvokeBuffer(const commandFn& fn, const Element& callback)
|
||||
{
|
||||
}
|
||||
void CommandWorker::Invoke(const voidFn& fn)
|
||||
{
|
||||
mWork.Invoke(fn);
|
||||
}
|
||||
|
||||
void CommandWorker::InvokeBuffer(const commandFn& fn, const voidFn& callback)
|
||||
{
|
||||
mWork.Invoke([=, this]() {
|
||||
Invoke([=, this]() {
|
||||
CommandBuffer cmd = mCommandPool.Pop();
|
||||
Buffer(cmd, fn, callback);
|
||||
mCommandPool.Push(cmd);
|
||||
});
|
||||
}
|
||||
void CommandWorker::Buffer(CommandBuffer& cmd, const commandFn& fn, const voidFn& callback)
|
||||
void CommandWorker::Buffer(CommandBuffer& cmd, const commandFn& fn, const Element& callback)
|
||||
{
|
||||
cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
||||
fn(cmd);
|
||||
@ -37,11 +22,26 @@ namespace vkn {
|
||||
|
||||
void CommandWorker::Flush()
|
||||
{
|
||||
mWork.SyncInvoke([]{});
|
||||
SyncInvoke([]{});
|
||||
}
|
||||
bool CommandWorker::Present(VkPresentInfoKHR& presentInfo)
|
||||
{
|
||||
VkResult result = vkQueuePresentKHR(mQueue.Ptr(), &presentInfo);
|
||||
return result == VK_SUCCESS;
|
||||
}
|
||||
void CommandWorker::SyncInvoke(const Element& fn)
|
||||
{
|
||||
Invoke([=, this]() {
|
||||
fn();
|
||||
mSemaphore.release();
|
||||
});
|
||||
mSemaphore.acquire();
|
||||
}
|
||||
void CommandWorker::Loop()
|
||||
{
|
||||
while (true) {
|
||||
Element elem = mChannel.acquire();
|
||||
elem();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
#include "vkn/thread/thread_worker.h"
|
||||
#include "zlog.h"
|
||||
namespace vkn {
|
||||
CommandThreadWorker::CommandThreadWorker(Name name, int buffer)
|
||||
: mName(name)
|
||||
, mChannel(buffer)
|
||||
, mSemaphore(0)
|
||||
{
|
||||
mThread = std::thread(&CommandThreadWorker::workloop, this);
|
||||
}
|
||||
CommandThreadWorker::~CommandThreadWorker() {
|
||||
zlog::info("~CommandThreadWorker");
|
||||
zlog::flush();
|
||||
}
|
||||
void CommandThreadWorker::workloop()
|
||||
{
|
||||
mThread.detach();
|
||||
while (true) {
|
||||
voidFn fn = mChannel.acquire();
|
||||
fn();
|
||||
}
|
||||
}
|
||||
void CommandThreadWorker::Invoke(const voidFn& fn)
|
||||
{
|
||||
mChannel.release(fn);
|
||||
}
|
||||
|
||||
void CommandThreadWorker::SyncInvoke(const voidFn& fn)
|
||||
{
|
||||
Invoke([=,this]() {
|
||||
fn();
|
||||
mSemaphore.release();
|
||||
});
|
||||
mSemaphore.acquire();
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,8 @@
|
||||
#include "vkn/vulkan_api.h"
|
||||
#include "vkn/vulkan_window.h"
|
||||
#include "vkn/wrapper/buffer.h"
|
||||
#include "vkn/thread/buffer_worker.h"
|
||||
#include "vkn/thread/command_worker.h"
|
||||
#include "render/asset/mesh.h"
|
||||
namespace vkn {
|
||||
VulkanAPI::VulkanAPI() : window(*VulkanWindow::Ptr()), backend(VulkanEngineName)
|
||||
@ -16,12 +19,29 @@ namespace vkn {
|
||||
}
|
||||
void VulkanAPI::SetStaticMesh(Mesh& mesh)
|
||||
{
|
||||
auto Indices = mesh.GetIndices();
|
||||
auto Vertices = mesh.GetVertices();
|
||||
auto& Indices = mesh.GetIndices();
|
||||
auto& Vertices = mesh.GetVertices();
|
||||
MeshVAO& VAO = MeshTable[mesh.GetGuid()];
|
||||
VAO.indexCount = Indices.size();
|
||||
VAO.vertexCount = Vertices.size();
|
||||
|
||||
Buffer indexBuffer{};
|
||||
indexBuffer.ppBuffer = &VAO.indexBuffer;
|
||||
indexBuffer.pCpuData = Indices.data();
|
||||
indexBuffer.size = sizeof(decltype(Indices[0])) * Indices.size();
|
||||
indexBuffer.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
||||
Backend::TransferWorker->Invoke(indexBuffer);
|
||||
|
||||
Buffer vertexBuffer{};
|
||||
vertexBuffer.ppBuffer = &VAO.vertexBuffer;
|
||||
vertexBuffer.pCpuData = Vertices.data();
|
||||
vertexBuffer.size = Vertices.data_size();
|
||||
vertexBuffer.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||
Backend::TransferWorker->Invoke(vertexBuffer);
|
||||
}
|
||||
void VulkanAPI::DrawStaticMesh(Mesh& mesh)
|
||||
{
|
||||
|
||||
}
|
||||
void VulkanAPI::LoadShader(Shader& shader)
|
||||
{
|
||||
|
||||
3
engine/modules/render/vulkan/src/wrapper/buffer.cpp
Normal file
3
engine/modules/render/vulkan/src/wrapper/buffer.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
namespace vkn{
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user