feat: 解析式 PBR(Cook-Torrance GGX,metallic-roughness 工作流)
- 修 void* 指针算术警告(Texture::InitFromDds) - Material:slot2 语义切为 metallicRoughness(glTF 约定 G=粗糙度 B=金属度)+ 新增材质因子参数 UBO(binding 4,per-slot ring, 创建时写死,metallic/roughness 因子乘 MR 贴图) - simple_shader.frag:Blinn-Phong → Cook-Torrance(GGX 分布 + Smith 几何 + Schlick Fresnel,k=(r+1)²/8 解析光源版);金属不参与 漫反射;环境光暂为常数(IBL 后续) - Model:读 aiTextureType_UNKNOWN(glTF MR 落点)+ AI_MATKEY_ METALLIC/ROUGHNESS_FACTOR(旧资产缺键退化为电介质 0/0.5); 材质缓存键含因子 - main.cpp:演示场景换回 backpack(旧资产走因子路径验证 PBR 全链路) - 旧 specular 贴图不再使用(语义被 MR 取代)
This commit is contained in:
+16
-16
@@ -18,7 +18,7 @@ namespace Engine
|
||||
|
||||
// ============ 资源计数 ============
|
||||
|
||||
void Stats::AddTexture(u64 bytes)
|
||||
void Stats::AddTexture(const u64 bytes)
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
m_TextureCount++;
|
||||
@@ -27,7 +27,7 @@ namespace Engine
|
||||
m_TotalAllocation += bytes;
|
||||
}
|
||||
|
||||
void Stats::RemoveTexture(u64 bytes)
|
||||
void Stats::RemoveTexture(const u64 bytes)
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
if (m_TextureCount > 0) m_TextureCount--;
|
||||
@@ -36,27 +36,27 @@ namespace Engine
|
||||
m_TotalDeallocation += bytes;
|
||||
}
|
||||
|
||||
void Stats::AddMesh(u64 vertexBytes, u64 indexBytes)
|
||||
void Stats::AddMesh(const u64 vertexBytes, const u64 indexBytes)
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
m_MeshCount++;
|
||||
u64 total = vertexBytes + indexBytes;
|
||||
const u64 total = vertexBytes + indexBytes;
|
||||
m_MeshBytes += total;
|
||||
m_FrameAllocation += total;
|
||||
m_TotalAllocation += total;
|
||||
}
|
||||
|
||||
void Stats::RemoveMesh(u64 vertexBytes, u64 indexBytes)
|
||||
void Stats::RemoveMesh(const u64 vertexBytes, const u64 indexBytes)
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
if (m_MeshCount > 0) m_MeshCount--;
|
||||
u64 total = vertexBytes + indexBytes;
|
||||
const u64 total = vertexBytes + indexBytes;
|
||||
if (m_MeshBytes >= total) m_MeshBytes -= total;
|
||||
m_FrameDeallocation += total;
|
||||
m_TotalDeallocation += total;
|
||||
}
|
||||
|
||||
void Stats::AddBuffer(u64 bytes)
|
||||
void Stats::AddBuffer(const u64 bytes)
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
m_BufferCount++;
|
||||
@@ -65,7 +65,7 @@ namespace Engine
|
||||
m_TotalAllocation += bytes;
|
||||
}
|
||||
|
||||
void Stats::RemoveBuffer(u64 bytes)
|
||||
void Stats::RemoveBuffer(const u64 bytes)
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
if (m_BufferCount > 0) m_BufferCount--;
|
||||
@@ -74,25 +74,25 @@ namespace Engine
|
||||
m_TotalDeallocation += bytes;
|
||||
}
|
||||
|
||||
void Stats::AddMemoryBlock(u64 bytes)
|
||||
void Stats::AddMemoryBlock(const u64 bytes)
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
m_MemoryBlockBytes += bytes;
|
||||
}
|
||||
|
||||
void Stats::RemoveMemoryBlock(u64 bytes)
|
||||
void Stats::RemoveMemoryBlock(const u64 bytes)
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
if (m_MemoryBlockBytes >= bytes) m_MemoryBlockBytes -= bytes;
|
||||
}
|
||||
|
||||
void Stats::AddMemoryUsed(u64 bytes)
|
||||
void Stats::AddMemoryUsed(const u64 bytes)
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
m_MemoryUsedBytes += bytes;
|
||||
}
|
||||
|
||||
void Stats::RemoveMemoryUsed(u64 bytes)
|
||||
void Stats::RemoveMemoryUsed(const u64 bytes)
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
if (m_MemoryUsedBytes >= bytes) m_MemoryUsedBytes -= bytes;
|
||||
@@ -111,14 +111,14 @@ namespace Engine
|
||||
{
|
||||
}
|
||||
|
||||
void Stats::AddAllocation(u64 bytes)
|
||||
void Stats::AddAllocation(const u64 bytes)
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
m_FrameAllocation += bytes;
|
||||
m_TotalAllocation += bytes;
|
||||
}
|
||||
|
||||
void Stats::AddDeallocation(u64 bytes)
|
||||
void Stats::AddDeallocation(const u64 bytes)
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
m_FrameDeallocation += bytes;
|
||||
@@ -206,13 +206,13 @@ namespace Engine
|
||||
|
||||
// ============ 打印 ============
|
||||
|
||||
static double MB(u64 bytes) { return bytes / (1024.0 * 1024.0); }
|
||||
static double MB(const u64 bytes) { return bytes / (1024.0 * 1024.0); }
|
||||
|
||||
void Stats::Print() const
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
|
||||
auto proc = ReadProcessMemory();
|
||||
const auto proc = ReadProcessMemory();
|
||||
|
||||
ENGINE_INFO("========== Resource Stats ==========");
|
||||
ENGINE_INFO("Textures: {:>4} ({:.2f} MB)", m_TextureCount, MB(m_TextureBytes));
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace Engine
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
vk::SurfaceKHR Window::CreateSurface(vk::Instance instance)
|
||||
vk::SurfaceKHR Window::CreateSurface(const vk::Instance instance) const
|
||||
{
|
||||
VkSurfaceKHR surface;
|
||||
if (glfwCreateWindowSurface(instance, m_Window, nullptr, &surface) != VK_SUCCESS)
|
||||
@@ -167,7 +167,7 @@ namespace Engine
|
||||
return surface;
|
||||
}
|
||||
|
||||
void Window::DestroySurface(vk::Instance instance, vk::SurfaceKHR surface)
|
||||
void Window::DestroySurface(const vk::Instance instance, const vk::SurfaceKHR surface)
|
||||
{
|
||||
instance.destroySurfaceKHR(surface);
|
||||
}
|
||||
@@ -184,14 +184,14 @@ namespace Engine
|
||||
glfwGetFramebufferSize(m_Window, &width, &height);
|
||||
}
|
||||
|
||||
bool Window::IsKeyPressed(int key) const
|
||||
bool Window::IsKeyPressed(const int key) const
|
||||
{
|
||||
// UI 捕获键盘时,轮询接口同样静默(相机等轮询型消费方)
|
||||
if (m_KeyboardCapture && m_KeyboardCapture()) return false;
|
||||
return glfwGetKey(m_Window, key) == GLFW_PRESS;
|
||||
}
|
||||
|
||||
void Window::GetMouseDelta(float& dx, float& dy)
|
||||
void Window::GetMouseDelta(float& dx, float& dy) const
|
||||
{
|
||||
double mx, my;
|
||||
glfwGetCursorPos(m_Window, &mx, &my);
|
||||
|
||||
@@ -7,14 +7,17 @@
|
||||
#include <Engine/Vulkan/MemoryAllocator.h>
|
||||
#include <Engine/Vulkan/DescriptorManager.h>
|
||||
#include <Engine/Vulkan/Texture.h>
|
||||
#include <Engine/Vulkan/UniformBuffer.h>
|
||||
#include <Engine/Core/FrameContext.h>
|
||||
#include <Engine/Core/Log.h>
|
||||
|
||||
namespace Engine
|
||||
{
|
||||
Material::Material(Device& device,
|
||||
Material::Material(Device& device, MemoryAllocator& allocator,
|
||||
DescriptorManager& descriptorManager,
|
||||
vk::DescriptorSetLayout layout,
|
||||
const std::array<Texture*, kSlotCount>& textures)
|
||||
const std::array<Texture*, kSlotCount>& textures,
|
||||
const MaterialParams& params)
|
||||
: m_Textures(textures)
|
||||
{
|
||||
m_DescriptorSet = descriptorManager.AllocateDescriptorSet(layout);
|
||||
@@ -25,18 +28,31 @@ namespace Engine
|
||||
m_Textures[slot]->GetSampler(),
|
||||
m_Textures[slot]->GetView());
|
||||
}
|
||||
|
||||
// 材质参数:per-slot ring,创建时写死(参数静态,无每帧更新)
|
||||
m_ParamsBuffer = CreateScope<UniformBuffer>(
|
||||
device, allocator, sizeof(MaterialParams), kMaxFramesInFlight);
|
||||
for (u32 slot = 0; slot < kMaxFramesInFlight; ++slot) {
|
||||
m_ParamsBuffer->Update(slot, ¶ms, sizeof(params));
|
||||
descriptorManager.UpdateUniformBuffer(
|
||||
m_DescriptorSet, kParamsBinding,
|
||||
m_ParamsBuffer->Get(slot), m_ParamsBuffer->GetSize());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Material::~Material() = default;
|
||||
|
||||
std::string Material::MakeCacheKey(const std::string paths[kSlotCount])
|
||||
std::string Material::MakeCacheKey(const std::string paths[kSlotCount],
|
||||
const MaterialParams& params)
|
||||
{
|
||||
std::string key;
|
||||
for (u32 slot = 0; slot < kSlotCount; ++slot) {
|
||||
if (slot) key += '\n';
|
||||
key += paths[slot];
|
||||
key += '\n';
|
||||
}
|
||||
key += "f:" + std::to_string(params.factors.x) +
|
||||
"," + std::to_string(params.factors.y);
|
||||
return key;
|
||||
}
|
||||
} // namespace Engine
|
||||
|
||||
@@ -38,13 +38,13 @@ Model::~Model() = default;
|
||||
void Model::InitDefaultTextures()
|
||||
{
|
||||
// 各材质槽位的兜底纹理(1x1,开销可忽略):
|
||||
// albedo 白(受光) / normal 平法线 (0.5,0.5,1) / specular 黑 / emissive 黑
|
||||
// albedo 白 / MR 平参数(roughness 0.5, metallic 0)/ emissive 黑
|
||||
m_DefaultTextures[Material::Albedo] =
|
||||
Texture::CreateSolidColor(m_Device, m_Allocator, 255, 255, 255);
|
||||
m_DefaultTextures[Material::MetallicRoughness] =
|
||||
Texture::CreateSolidColor(m_Device, m_Allocator, 0, 128, 0, false);
|
||||
m_DefaultTextures[Material::Normal] =
|
||||
Texture::CreateSolidColor(m_Device, m_Allocator, 128, 128, 255, false);
|
||||
m_DefaultTextures[Material::Specular] =
|
||||
Texture::CreateSolidColor(m_Device, m_Allocator, 0, 0, 0, false);
|
||||
m_DefaultTextures[Material::Emissive] =
|
||||
Texture::CreateSolidColor(m_Device, m_Allocator, 0, 0, 0);
|
||||
}
|
||||
@@ -74,7 +74,7 @@ Model::Model(Device& device, MemoryAllocator& allocator,
|
||||
|
||||
// 材质/纹理生命周期随模型(缓存持有)
|
||||
std::string paths[Material::kSlotCount] = {"", "", "", ""};
|
||||
Material* mat = GetOrCreateMaterial(paths); // 全默认材质
|
||||
Material* mat = GetOrCreateMaterial(paths, MaterialParams{}); // 全默认材质
|
||||
|
||||
m_Meshes.push_back(CreateScope<Mesh>(
|
||||
m_Device, m_Allocator, vertices, indices, mat));
|
||||
@@ -148,9 +148,10 @@ Texture* Model::GetOrLoadTexture(const std::string& rawPath, bool srgb)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
Material* Model::GetOrCreateMaterial(const std::string paths[Material::kSlotCount])
|
||||
Material* Model::GetOrCreateMaterial(const std::string paths[Material::kSlotCount],
|
||||
const MaterialParams& params)
|
||||
{
|
||||
const std::string key = Material::MakeCacheKey(paths);
|
||||
const std::string key = Material::MakeCacheKey(paths, params);
|
||||
if (auto it = m_MaterialCache.find(key); it != m_MaterialCache.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
@@ -169,7 +170,8 @@ Material* Model::GetOrCreateMaterial(const std::string paths[Material::kSlotCoun
|
||||
}
|
||||
|
||||
auto mat = CreateScope<Material>(
|
||||
m_Device, m_DescriptorManager, m_TextureLayout, textures);
|
||||
m_Device, m_Allocator, m_DescriptorManager, m_TextureLayout,
|
||||
textures, params);
|
||||
Material* ptr = mat.get();
|
||||
m_MaterialCache.emplace(key, std::move(mat));
|
||||
return ptr;
|
||||
@@ -225,18 +227,20 @@ Scope<Mesh> Model::ProcessMesh(aiMesh* mesh, const aiScene* scene)
|
||||
}
|
||||
}
|
||||
|
||||
// 读取材质纹理路径(4 槽:albedo/normal/specular/emissive)
|
||||
// 读取材质纹理路径(PBR metallic-roughness 槽位)+ 金属度/粗糙度因子
|
||||
std::string texPaths[Material::kSlotCount];
|
||||
MaterialParams params;
|
||||
|
||||
if (mesh->mMaterialIndex >= 0) {
|
||||
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
|
||||
const std::filesystem::path modelDir =
|
||||
std::filesystem::path(m_ModelPath).parent_path();
|
||||
|
||||
// glTF 的 metallicRoughness 贴图落在 aiTextureType_UNKNOWN
|
||||
const std::pair<aiTextureType, u32> slots[] = {
|
||||
{aiTextureType_DIFFUSE, Material::Albedo},
|
||||
{aiTextureType_NORMALS, Material::Normal},
|
||||
{aiTextureType_SPECULAR, Material::Specular},
|
||||
{aiTextureType_UNKNOWN, Material::MetallicRoughness},
|
||||
{aiTextureType_EMISSIVE, Material::Emissive},
|
||||
};
|
||||
|
||||
@@ -247,10 +251,17 @@ Scope<Mesh> Model::ProcessMesh(aiMesh* mesh, const aiScene* scene)
|
||||
texPaths[slot] = (modelDir / path.C_Str()).string();
|
||||
}
|
||||
}
|
||||
|
||||
// PBR 因子(glTF2 材质属性;旧资产无此键 → 默认电介质 0/0.5)
|
||||
ai_real metallic = 0.0f, roughness = 0.5f;
|
||||
material->Get(AI_MATKEY_METALLIC_FACTOR, metallic);
|
||||
material->Get(AI_MATKEY_ROUGHNESS_FACTOR, roughness);
|
||||
params.factors = glm::vec4(static_cast<f32>(metallic),
|
||||
static_cast<f32>(roughness), 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
// 材质缓存:同贴图组合 → 同一 Material(一个描述符集),mesh 数 ≠ 集数
|
||||
Material* mat = GetOrCreateMaterial(texPaths);
|
||||
// 材质缓存:同贴图组合+因子 → 同一 Material(一个描述符集)
|
||||
Material* mat = GetOrCreateMaterial(texPaths, params);
|
||||
|
||||
return CreateScope<Mesh>(
|
||||
m_Device, m_Allocator, vertices, indices, mat);
|
||||
|
||||
@@ -32,14 +32,17 @@ namespace Engine::Passes
|
||||
};
|
||||
uboSetLayout = descriptors.CreateLayout(uboBindings);
|
||||
|
||||
// Set 1: 材质纹理槽(binding = Material::Slot:0 albedo / 1 normal /
|
||||
// 2 specular / 3 emissive)
|
||||
// Set 1: PBR 材质纹理槽(binding = Material::Slot:0 albedo /
|
||||
// 1 normal / 2 metallicRoughness / 3 emissive)+ 参数 UBO(binding 4)
|
||||
std::vector<DescriptorBinding> texBindings;
|
||||
for (u32 slot = 0; slot < Material::kSlotCount; ++slot) {
|
||||
texBindings.push_back(
|
||||
{slot, vk::DescriptorType::eCombinedImageSampler,
|
||||
vk::ShaderStageFlagBits::eFragment});
|
||||
}
|
||||
texBindings.push_back(
|
||||
{Material::kParamsBinding, vk::DescriptorType::eUniformBuffer,
|
||||
vk::ShaderStageFlagBits::eFragment});
|
||||
textureSetLayout = descriptors.CreateLayout(texBindings);
|
||||
|
||||
// Set 2: CSM 级联阴影图(fragment 采样,binding = 级联序号)
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
namespace Engine {
|
||||
|
||||
Buffer::Buffer(Device& device, MemoryAllocator& allocator,
|
||||
vk::DeviceSize size, vk::BufferUsageFlags usage,
|
||||
vk::MemoryPropertyFlags memProps)
|
||||
: m_Device(device), m_Allocator(allocator) , m_Size(size)
|
||||
const vk::DeviceSize size, const vk::BufferUsageFlags usage,
|
||||
const vk::MemoryPropertyFlags memProps)
|
||||
: m_Device(device), m_Size(size) , m_Allocator(allocator)
|
||||
{
|
||||
// VMA 惯用法:创建 + 分配 + 绑定一步完成;
|
||||
// HOST_VISIBLE 时持久映射,MappedPtr 直接可用
|
||||
@@ -33,7 +33,7 @@ namespace Engine {
|
||||
STATS.RemoveBuffer(m_Size);
|
||||
}
|
||||
|
||||
void Buffer::Upload(const void* data, vk::DeviceSize size, vk::DeviceSize offset)
|
||||
void Buffer::Upload(const void* data, const vk::DeviceSize size, const vk::DeviceSize offset) const
|
||||
{
|
||||
if (!m_MappedPtr) {
|
||||
ENGINE_ERROR("Buffer::Upload: buffer is not host visible");
|
||||
|
||||
@@ -35,9 +35,9 @@ namespace Engine {
|
||||
m_Device.GetDevice().destroyCommandPool(m_Pool);
|
||||
}
|
||||
|
||||
vk::CommandBuffer CommandManager::BeginFrame(u32 frameSlot)
|
||||
vk::CommandBuffer CommandManager::BeginFrame(const u32 frameSlot) const
|
||||
{
|
||||
auto cmd = m_Buffers[frameSlot];
|
||||
const auto cmd = m_Buffers[frameSlot];
|
||||
cmd.reset();
|
||||
|
||||
vk::CommandBufferBeginInfo beginInfo;
|
||||
@@ -47,7 +47,7 @@ namespace Engine {
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void CommandManager::EndFrame(u32 frameSlot)
|
||||
void CommandManager::EndFrame(const u32 frameSlot) const
|
||||
{
|
||||
m_Buffers[frameSlot].end();
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ namespace Engine
|
||||
|
||||
DescriptorManager::~DescriptorManager()
|
||||
{
|
||||
for (auto pool : m_Pools) {
|
||||
for (const auto pool : m_Pools) {
|
||||
m_Device.GetDevice().destroyDescriptorPool(pool);
|
||||
}
|
||||
}
|
||||
|
||||
vk::DescriptorPool DescriptorManager::CreateChunk()
|
||||
vk::DescriptorPool DescriptorManager::CreateChunk() const
|
||||
{
|
||||
std::array<vk::DescriptorPoolSize, 3> poolSizes = {
|
||||
vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, kChunkSets),
|
||||
@@ -39,7 +39,7 @@ namespace Engine
|
||||
return m_Device.GetDevice().createDescriptorPool(poolInfo);
|
||||
}
|
||||
|
||||
vk::DescriptorSetLayout DescriptorManager::CreateLayout(const std::vector<DescriptorBinding>& bindings)
|
||||
vk::DescriptorSetLayout DescriptorManager::CreateLayout(const std::vector<DescriptorBinding>& bindings) const
|
||||
{
|
||||
std::vector<vk::DescriptorSetLayoutBinding> vkBindings;
|
||||
for (auto& b : bindings)
|
||||
@@ -80,8 +80,8 @@ namespace Engine
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptorManager::UpdateUniformBuffer(vk::DescriptorSet set, u32 binding,
|
||||
vk::Buffer buffer, u64 size)
|
||||
void DescriptorManager::UpdateUniformBuffer(const vk::DescriptorSet set, const u32 binding,
|
||||
const vk::Buffer buffer, const u64 size) const
|
||||
{
|
||||
vk::DescriptorBufferInfo bufferInfo;
|
||||
bufferInfo.setBuffer(buffer).setOffset(0).setRange(size);
|
||||
@@ -97,8 +97,8 @@ namespace Engine
|
||||
m_Device.GetDevice().updateDescriptorSets(write, {});
|
||||
}
|
||||
|
||||
void DescriptorManager::UpdateStorageBuffer(vk::DescriptorSet set, u32 binding,
|
||||
vk::Buffer buffer, u64 size)
|
||||
void DescriptorManager::UpdateStorageBuffer(const vk::DescriptorSet set, const u32 binding,
|
||||
const vk::Buffer buffer, const u64 size) const
|
||||
{
|
||||
vk::DescriptorBufferInfo bufferInfo;
|
||||
bufferInfo.setBuffer(buffer).setOffset(0).setRange(size);
|
||||
@@ -114,8 +114,8 @@ namespace Engine
|
||||
m_Device.GetDevice().updateDescriptorSets(write, {});
|
||||
}
|
||||
|
||||
void DescriptorManager::UpdateTexture(vk::DescriptorSet set, u32 binding,
|
||||
vk::Sampler sampler, vk::ImageView view)
|
||||
void DescriptorManager::UpdateTexture(const vk::DescriptorSet set, const u32 binding,
|
||||
const vk::Sampler sampler, const vk::ImageView view) const
|
||||
{
|
||||
vk::DescriptorImageInfo imageInfo;
|
||||
imageInfo.setSampler(sampler)
|
||||
@@ -134,7 +134,7 @@ namespace Engine
|
||||
}
|
||||
|
||||
vk::PipelineLayout DescriptorManager::CreatePipelineLayout(vk::DescriptorSetLayout layout,
|
||||
const u32 pushConstantSize)
|
||||
const u32 pushConstantSize) const
|
||||
{
|
||||
vk::PipelineLayoutCreateInfo info;
|
||||
info.setSetLayouts(layout);
|
||||
@@ -154,7 +154,7 @@ namespace Engine
|
||||
}
|
||||
|
||||
vk::PipelineLayout DescriptorManager::CreatePipelineLayout(const std::vector<vk::DescriptorSetLayout>& layouts,
|
||||
u32 pushConstantSize)
|
||||
const u32 pushConstantSize) const
|
||||
{
|
||||
vk::PipelineLayoutCreateInfo info;
|
||||
info.setSetLayouts(layouts);
|
||||
|
||||
@@ -21,11 +21,11 @@ ShaderManager::~ShaderManager()
|
||||
}
|
||||
|
||||
ShaderObject ShaderManager::CreateFromFile(const std::string& spvPath,
|
||||
vk::ShaderStageFlagBits stage,
|
||||
const vk::ShaderStageFlagBits stage,
|
||||
const std::vector<vk::DescriptorSetLayout>& layouts,
|
||||
u32 pushConstantSize)
|
||||
const u32 pushConstantSize)
|
||||
{
|
||||
auto spirv = ReadSPIRV(spvPath);
|
||||
const auto spirv = ReadSPIRV(spvPath);
|
||||
if (spirv.empty()) {
|
||||
ENGINE_ERROR("Failed to read SPIR-V: {}", spvPath);
|
||||
return { nullptr, stage };
|
||||
@@ -34,9 +34,9 @@ ShaderObject ShaderManager::CreateFromFile(const std::string& spvPath,
|
||||
}
|
||||
|
||||
ShaderObject ShaderManager::CreateFromSPIRV(const std::vector<u32>& spirv,
|
||||
vk::ShaderStageFlagBits stage,
|
||||
const vk::ShaderStageFlagBits stage,
|
||||
const std::vector<vk::DescriptorSetLayout>& layouts,
|
||||
u32 pushConstantSize)
|
||||
const u32 pushConstantSize) const
|
||||
{
|
||||
vk::ShaderStageFlags nextStage = {};
|
||||
if (stage == vk::ShaderStageFlagBits::eVertex) {
|
||||
@@ -70,7 +70,7 @@ ShaderObject ShaderManager::CreateFromSPIRV(const std::vector<u32>& spirv,
|
||||
|
||||
vk::ShaderEXT shader;
|
||||
try {
|
||||
auto result = m_Device.GetDevice().createShadersEXT(createInfo);
|
||||
const auto result = m_Device.GetDevice().createShadersEXT(createInfo);
|
||||
shader = result.value[0];
|
||||
}
|
||||
catch (const vk::SystemError& e) {
|
||||
@@ -81,7 +81,7 @@ ShaderObject ShaderManager::CreateFromSPIRV(const std::vector<u32>& spirv,
|
||||
return { shader, stage };
|
||||
}
|
||||
|
||||
void ShaderManager::Destroy(const ShaderObject& shader)
|
||||
void ShaderManager::Destroy(const ShaderObject& shader) const
|
||||
{
|
||||
if (shader.Handle) {
|
||||
m_Device.GetDevice().destroyShaderEXT(shader.Handle);
|
||||
@@ -96,7 +96,7 @@ std::vector<u32> ShaderManager::ReadSPIRV(const std::string& path)
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t size = file.tellg();
|
||||
const size_t size = file.tellg();
|
||||
std::vector<u32> buffer(size / sizeof(u32));
|
||||
file.seekg(0);
|
||||
file.read(reinterpret_cast<char*>(buffer.data()), size);
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Engine {
|
||||
SyncManager::SyncManager(Device& device, u32 maxFramesInFlight, u32 imageCount)
|
||||
: m_Device(device)
|
||||
{
|
||||
vk::SemaphoreCreateInfo semInfo;
|
||||
const vk::SemaphoreCreateInfo semInfo;
|
||||
|
||||
// 每帧一个 ImageAvailable
|
||||
m_ImageAvailable.resize(maxFramesInFlight);
|
||||
@@ -48,7 +48,7 @@ namespace Engine {
|
||||
for (auto s : m_RenderFinished) vkDevice.destroySemaphore(s);
|
||||
}
|
||||
|
||||
void SyncManager::WaitFence(u32 frameIndex)
|
||||
void SyncManager::WaitFence(const u32 frameIndex) const
|
||||
{
|
||||
auto result = m_Device.GetDevice().waitForFences(
|
||||
m_FrameFences[frameIndex], VK_TRUE, std::numeric_limits<u64>::max());
|
||||
@@ -57,7 +57,7 @@ namespace Engine {
|
||||
}
|
||||
}
|
||||
|
||||
void SyncManager::ResetFence(u32 frameIndex)
|
||||
void SyncManager::ResetFence(const u32 frameIndex) const
|
||||
{
|
||||
m_Device.GetDevice().resetFences(m_FrameFences[frameIndex]);
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ namespace Engine
|
||||
// DDS → Vulkan 格式映射。sRGB 语义由贴图槽位决定(渲染侧职责):
|
||||
// 颜色图(BaseColor/Emissive)→ SRGB 变体
|
||||
// 数据图(Normal/Specular 等线性槽位)→ UNORM
|
||||
vk::Format ToVkFormat(Assets::Dds::DdsFormat f, bool srgb)
|
||||
vk::Format ToVkFormat(const Assets::Dds::DdsFormat f, const bool srgb)
|
||||
{
|
||||
using DF = Assets::Dds::DdsFormat;
|
||||
switch (f) {
|
||||
@@ -279,9 +279,10 @@ namespace Engine
|
||||
std::vector<vk::DeviceSize> offsets(m_MipLevels);
|
||||
{
|
||||
vk::DeviceSize off = 0;
|
||||
auto* dst = static_cast<u8*>(stagingAlloc.MappedPtr);
|
||||
for (u32 mip = 0; mip < m_MipLevels; ++mip) {
|
||||
offsets[mip] = off;
|
||||
std::memcpy(stagingAlloc.MappedPtr + off,
|
||||
std::memcpy(dst + off,
|
||||
data.Mips[mip].data(), data.Mips[mip].size());
|
||||
off += data.Mips[mip].size();
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Engine {
|
||||
ENGINE_INFO("UniformBuffer created: {} bytes x {} frames", size, frameCount);
|
||||
}
|
||||
|
||||
void UniformBuffer::Update(u32 frameSlot, const void* data, u64 size)
|
||||
void UniformBuffer::Update(const u32 frameSlot, const void* data, const u64 size) const
|
||||
{
|
||||
m_Buffers[frameSlot]->Upload(data, size);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user