添加多模型渲染,添加贴图渲染,添加平行光, 暂时不上传assets

This commit is contained in:
2026-09-21 14:07:20 +08:00
parent 381b7c0aa6
commit 7d628f8d8a
37 changed files with 9817 additions and 189 deletions
+324
View File
@@ -0,0 +1,324 @@
//
// Created by atdunbg on 2026/9/21.
//
#include <Engine/Core/Stats.h>
#include <Engine/Core/Log.h>
#include <fstream>
#include <sstream>
#include <string>
namespace Engine
{
Stats& Stats::Get()
{
static Stats instance;
return instance;
}
// ============ 资源计数 ============
void Stats::AddTexture(u64 bytes)
{
std::lock_guard lock(m_Mutex);
m_TextureCount++;
m_TextureBytes += bytes;
m_FrameAllocation += bytes;
m_TotalAllocation += bytes;
}
void Stats::RemoveTexture(u64 bytes)
{
std::lock_guard lock(m_Mutex);
if (m_TextureCount > 0) m_TextureCount--;
if (m_TextureBytes >= bytes) m_TextureBytes -= bytes;
m_FrameDeallocation += bytes;
m_TotalDeallocation += bytes;
}
void Stats::AddMesh(u64 vertexBytes, u64 indexBytes)
{
std::lock_guard lock(m_Mutex);
m_MeshCount++;
u64 total = vertexBytes + indexBytes;
m_MeshBytes += total;
m_FrameAllocation += total;
m_TotalAllocation += total;
}
void Stats::RemoveMesh(u64 vertexBytes, u64 indexBytes)
{
std::lock_guard lock(m_Mutex);
if (m_MeshCount > 0) m_MeshCount--;
u64 total = vertexBytes + indexBytes;
if (m_MeshBytes >= total) m_MeshBytes -= total;
m_FrameDeallocation += total;
m_TotalDeallocation += total;
}
void Stats::AddBuffer(u64 bytes)
{
std::lock_guard lock(m_Mutex);
m_BufferCount++;
m_BufferBytes += bytes;
m_FrameAllocation += bytes;
m_TotalAllocation += bytes;
}
void Stats::RemoveBuffer(u64 bytes)
{
std::lock_guard lock(m_Mutex);
if (m_BufferCount > 0) m_BufferCount--;
if (m_BufferBytes >= bytes) m_BufferBytes -= bytes;
m_FrameDeallocation += bytes;
m_TotalDeallocation += bytes;
}
void Stats::AddMemoryBlock(u64 bytes)
{
std::lock_guard lock(m_Mutex);
m_MemoryBlockBytes += bytes;
}
void Stats::RemoveMemoryBlock(u64 bytes)
{
std::lock_guard lock(m_Mutex);
if (m_MemoryBlockBytes >= bytes) m_MemoryBlockBytes -= bytes;
}
void Stats::AddMemoryUsed(u64 bytes)
{
std::lock_guard lock(m_Mutex);
m_MemoryUsedBytes += bytes;
}
void Stats::RemoveMemoryUsed(u64 bytes)
{
std::lock_guard lock(m_Mutex);
if (m_MemoryUsedBytes >= bytes) m_MemoryUsedBytes -= bytes;
}
// ============ 每帧 ============
void Stats::BeginFrame()
{
std::lock_guard lock(m_Mutex);
m_FrameAllocation = 0;
m_FrameDeallocation = 0;
}
void Stats::EndFrame()
{
}
void Stats::AddAllocation(u64 bytes)
{
std::lock_guard lock(m_Mutex);
m_FrameAllocation += bytes;
m_TotalAllocation += bytes;
}
void Stats::AddDeallocation(u64 bytes)
{
std::lock_guard lock(m_Mutex);
m_FrameDeallocation += bytes;
m_TotalDeallocation += bytes;
}
// ============ 进程内存采样 ============
Stats::ProcessMemory Stats::ReadProcessMemory() const
{
ProcessMemory result;
// ---- 1. 从 /proc/self/status 读 VmRSS 和 VmSize ----
// 这是内核报告的权威 RSS。smaps_rollup 会漏掉某些 NVIDIA 显存映射,
// 但 status 的 VmRSS 包含所有 VMA。
{
std::ifstream status("/proc/self/status");
std::string line;
while (std::getline(status, line))
{
if (line.rfind("VmRSS:", 0) == 0)
{
std::istringstream iss(line.substr(6));
u64 kb = 0;
iss >> kb;
result.Rss = kb * 1024;
}
else if (line.rfind("VmSize:", 0) == 0)
{
std::istringstream iss(line.substr(7));
u64 kb = 0;
iss >> kb;
result.VmSize = kb * 1024;
}
}
}
// ---- 2. 从 /proc/self/smaps_rollup 读 PSS 和分项 ----
// 注意:Rss 不从这里读,用上面的。
{
std::ifstream smaps("/proc/self/smaps_rollup");
std::string line;
while (std::getline(smaps, line))
{
std::istringstream iss(line);
std::string key;
u64 value = 0;
std::string unit;
iss >> key;
if (key.empty()) continue;
if (key.back() == ':') key.pop_back();
if (key == "Pss")
{
iss >> value >> unit;
result.Pss = value * 1024;
}
else if (key == "Shared_Clean")
{
iss >> value >> unit;
result.SharedClean = value * 1024;
}
else if (key == "Private_Dirty")
{
iss >> value >> unit;
result.PrivateDirty = value * 1024;
}
else if (key == "Private_Clean")
{
iss >> value >> unit;
result.PrivateClean = value * 1024;
}
}
}
return result;
}
void Stats::SampleProcessMemory()
{
std::lock_guard lock(m_Mutex);
m_ProcessMem = ReadProcessMemory();
}
// ============ 打印 ============
static double MB(u64 bytes) { return bytes / (1024.0 * 1024.0); }
void Stats::Print() const
{
std::lock_guard lock(m_Mutex);
auto proc = ReadProcessMemory();
ENGINE_INFO("========== Resource Stats ==========");
ENGINE_INFO("Textures: {:>4} ({:.2f} MB)", m_TextureCount, MB(m_TextureBytes));
ENGINE_INFO("Meshes: {:>4} ({:.2f} MB)", m_MeshCount, MB(m_MeshBytes));
ENGINE_INFO("Buffers: {:>4} ({:.2f} MB)", m_BufferCount, MB(m_BufferBytes));
ENGINE_INFO("--- GPU MemoryAllocator ---");
ENGINE_INFO("Allocated: {:.2f} MB", MB(m_MemoryBlockBytes));
ENGINE_INFO("Used: {:.2f} MB", MB(m_MemoryUsedBytes));
ENGINE_INFO("Wasted: {:.2f} MB", MB(m_MemoryBlockBytes - m_MemoryUsedBytes));
ENGINE_INFO("--- Process Memory ---");
ENGINE_INFO("VmSize: {:.2f} MB", MB(proc.VmSize));
ENGINE_INFO("RSS (resident): {:.2f} MB", MB(proc.Rss));
ENGINE_INFO("PSS: {:.2f} MB", MB(proc.Pss));
ENGINE_INFO(" Shared Clean: {:.2f} MB", MB(proc.SharedClean));
ENGINE_INFO(" Private Dirty: {:.2f} MB", MB(proc.PrivateDirty));
ENGINE_INFO(" Private Clean: {:.2f} MB", MB(proc.PrivateClean));
ENGINE_INFO("====================================");
}
void Stats::PrintDetailed() const
{
std::lock_guard lock(m_Mutex);
auto proc = ReadProcessMemory();
ENGINE_INFO("==================== Detailed Memory Stats ====================");
ENGINE_INFO(" Resources");
ENGINE_INFO(" Textures: {:>6} {:>10.2f} MB", m_TextureCount, MB(m_TextureBytes));
ENGINE_INFO(" Meshes: {:>6} {:>10.2f} MB", m_MeshCount, MB(m_MeshBytes));
ENGINE_INFO(" Buffers: {:>6} {:>10.2f} MB", m_BufferCount, MB(m_BufferBytes));
ENGINE_INFO(" Total: {:>10.2f} MB",
MB(m_TextureBytes + m_MeshBytes + m_BufferBytes));
ENGINE_INFO(" GPU MemoryAllocator");
ENGINE_INFO(" Allocated: {:>10.2f} MB", MB(m_MemoryBlockBytes));
ENGINE_INFO(" Used: {:>10.2f} MB", MB(m_MemoryUsedBytes));
ENGINE_INFO(" Wasted: {:>10.2f} MB",
MB(m_MemoryBlockBytes - m_MemoryUsedBytes));
ENGINE_INFO(" Allocation Churn");
ENGINE_INFO(" This frame: +{:.2f} MB / -{:.2f} MB",
MB(m_FrameAllocation), MB(m_FrameDeallocation));
ENGINE_INFO(" Total: +{:.2f} MB / -{:.2f} MB",
MB(m_TotalAllocation), MB(m_TotalDeallocation));
ENGINE_INFO(" Process Memory (/proc/self/status + smaps_rollup)");
ENGINE_INFO(" VmSize: {:>10.2f} MB", MB(proc.VmSize));
ENGINE_INFO(" RSS: {:>10.2f} MB", MB(proc.Rss));
ENGINE_INFO(" PSS: {:>10.2f} MB", MB(proc.Pss));
ENGINE_INFO(" Shared Clean: {:>10.2f} MB", MB(proc.SharedClean));
ENGINE_INFO(" Private Dirty: {:>10.2f} MB", MB(proc.PrivateDirty));
ENGINE_INFO(" Private Clean: {:>10.2f} MB", MB(proc.PrivateClean));
ENGINE_INFO(" Unaccounted (RSS - GPU Blocks)");
u64 engineTotal = m_MemoryBlockBytes;
if (proc.Rss > engineTotal)
{
ENGINE_INFO(" {:.2f} MB (Vulkan driver, libs, stack, heap, ...)",
MB(proc.Rss - engineTotal));
}
else
{
ENGINE_INFO(" (GPU blocks are the bulk of RSS)");
}
ENGINE_INFO("===============================================================");
}
void Stats::PrintComparison() const
{
std::lock_guard lock(m_Mutex);
auto proc = ReadProcessMemory();
u64 resourceTotal = m_TextureBytes + m_MeshBytes + m_BufferBytes;
ENGINE_INFO("=============== Memory Comparison ===============");
ENGINE_INFO("");
ENGINE_INFO("[Engine 自己统计]");
ENGINE_INFO(" Textures {:>10.2f} MB", MB(m_TextureBytes));
ENGINE_INFO(" Meshes {:>10.2f} MB", MB(m_MeshBytes));
ENGINE_INFO(" Buffers {:>10.2f} MB", MB(m_BufferBytes));
ENGINE_INFO(" ─────────────────────────────────────");
ENGINE_INFO(" 资源合计 {:>10.2f} MB", MB(resourceTotal));
ENGINE_INFO("");
ENGINE_INFO(" Allocator Used {:>10.2f} MB", MB(m_MemoryUsedBytes));
ENGINE_INFO(" Allocator Allocated {:>10.2f} MB", MB(m_MemoryBlockBytes));
ENGINE_INFO(" Allocator Wasted {:>10.2f} MB",
MB(m_MemoryBlockBytes - m_MemoryUsedBytes));
ENGINE_INFO("");
ENGINE_INFO("[系统 /proc 读出的]");
ENGINE_INFO(" VmRSS {:>10.2f} MB", MB(proc.Rss));
ENGINE_INFO(" VmSize {:>10.2f} MB", MB(proc.VmSize));
ENGINE_INFO(" PSS {:>10.2f} MB", MB(proc.Pss));
ENGINE_INFO(" Shared Clean {:>10.2f} MB", MB(proc.SharedClean));
ENGINE_INFO(" Private Dirty {:>10.2f} MB", MB(proc.PrivateDirty));
ENGINE_INFO(" Private Clean {:>10.2f} MB", MB(proc.PrivateClean));
ENGINE_INFO("");
ENGINE_INFO("[差值]");
ENGINE_INFO(" RSS - Allocator {:>10.2f} MB (Vulkan 驱动 + libs + 栈堆)",
MB(proc.Rss > m_MemoryBlockBytes ? proc.Rss - m_MemoryBlockBytes : 0));
ENGINE_INFO(" RSS - 资源合计 {:>10.2f} MB (含分配器碎片)",
MB(proc.Rss > resourceTotal ? proc.Rss - resourceTotal : 0));
ENGINE_INFO(" Allocated - Used {:>10.2f} MB (分配器空闲块)",
MB(m_MemoryBlockBytes - m_MemoryUsedBytes));
ENGINE_INFO("================================================");
}
} // namespace Engine
+56 -7
View File
@@ -8,32 +8,46 @@
#include <GLFW/glfw3.h>
namespace Engine {
namespace Engine
{
void Window::FramebufferResizeCallback(GLFWwindow* window, int width, int height)
{
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
self->m_FramebufferResized = true;
}
Window::Window(const std::string& title, u32 width, u32 height)
: m_Width(width), m_Height(height), m_Title(title)
{
if (!glfwInit()) {
if (!glfwInit())
{
ENGINE_FATAL("glfwInit failed");
return;
}
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
// glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
m_Window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
if (!m_Window) {
if (!m_Window)
{
ENGINE_FATAL("glfwCreateWindow failed");
glfwTerminate();
return;
}
ENGINE_INFO("Window created: {} ({}x{})", title, width, height);
// callbacks
glfwSetWindowUserPointer(m_Window, this);
glfwSetFramebufferSizeCallback(m_Window, FramebufferResizeCallback);
}
Window::~Window()
{
if (m_Window) {
if (m_Window)
{
glfwDestroyWindow(m_Window);
}
glfwTerminate();
@@ -52,7 +66,8 @@ namespace Engine {
vk::SurfaceKHR Window::CreateSurface(vk::Instance instance)
{
VkSurfaceKHR surface;
if (glfwCreateWindowSurface(instance, m_Window, nullptr, &surface) != VK_SUCCESS) {
if (glfwCreateWindowSurface(instance, m_Window, nullptr, &surface) != VK_SUCCESS)
{
ENGINE_FATAL("glfwCreateWindowSurface failed");
return nullptr;
}
@@ -71,4 +86,38 @@ namespace Engine {
return std::vector<const char*>(extensions, extensions + count);
}
} // namespace Engine
void Window::GetFramebufferSize(int& width, int& height) const
{
glfwGetFramebufferSize(m_Window, &width, &height);
}
bool Window::IsKeyPressed(int key) const
{
return glfwGetKey(m_Window, key) == GLFW_PRESS;
}
void Window::GetMouseDelta(float& dx, float& dy)
{
double mx, my;
glfwGetCursorPos(m_Window, &mx, &my);
static double lastX = mx;
static double lastY = my;
static bool first = true;
if (first)
{
lastX = mx;
lastY = my;
first = false;
dx = dy = 0.0f;
return;
}
dx = static_cast<float>(mx - lastX);
dy = static_cast<float>(my - lastY);
lastX = mx;
lastY = my;
}
} // namespace Engine