GroveEngine/modules/BgfxRenderer/Resources/ResourceCache.cpp
StillHammer 1443c1209e feat(BgfxRenderer): Complete Phase 2-3 with shaders and triangle rendering
Phase 2 - RHI Layer:
- Fix Command struct default constructor for union with non-trivial types
- Add missing mutex includes in ResourceCache.cpp
- Fix const_cast for getChildReadOnly in SceneCollector

Phase 3 - Shaders & Visual Test:
- Add ShaderManager for centralized shader loading
- Embed pre-compiled shaders (OpenGL, Vulkan, DX11, Metal)
- Add test_20_bgfx_rhi: 23 unit tests for RHI components
- Add test_21_bgfx_triangle: visual test rendering colored triangle

Test results:
- RHI unit tests: 23/23 passing
- Visual test: ~567 FPS with Vulkan renderer

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 16:43:17 +08:00

125 lines
3.3 KiB
C++

#include "ResourceCache.h"
#include "../RHI/RHIDevice.h"
#include <mutex>
#include <shared_mutex>
namespace grove {
rhi::TextureHandle ResourceCache::getTexture(const std::string& path) const {
std::shared_lock lock(m_mutex);
auto it = m_textures.find(path);
if (it != m_textures.end()) {
return it->second;
}
return rhi::TextureHandle{}; // Invalid handle
}
rhi::ShaderHandle ResourceCache::getShader(const std::string& name) const {
std::shared_lock lock(m_mutex);
auto it = m_shaders.find(name);
if (it != m_shaders.end()) {
return it->second;
}
return rhi::ShaderHandle{}; // Invalid handle
}
rhi::TextureHandle ResourceCache::loadTexture(rhi::IRHIDevice& device, const std::string& path) {
// Check if already loaded
{
std::shared_lock lock(m_mutex);
auto it = m_textures.find(path);
if (it != m_textures.end()) {
return it->second;
}
}
// Load texture data from file
// TODO: Use stb_image or similar to load actual texture files
// For now, create a placeholder 1x1 white texture
uint32_t whitePixel = 0xFFFFFFFF;
rhi::TextureDesc desc;
desc.width = 1;
desc.height = 1;
desc.mipLevels = 1;
desc.format = rhi::TextureDesc::RGBA8;
desc.data = &whitePixel;
desc.dataSize = sizeof(whitePixel);
rhi::TextureHandle handle = device.createTexture(desc);
// Store in cache
{
std::unique_lock lock(m_mutex);
m_textures[path] = handle;
}
return handle;
}
rhi::ShaderHandle ResourceCache::loadShader(rhi::IRHIDevice& device, const std::string& name,
const void* vsData, uint32_t vsSize,
const void* fsData, uint32_t fsSize) {
// Check if already loaded
{
std::shared_lock lock(m_mutex);
auto it = m_shaders.find(name);
if (it != m_shaders.end()) {
return it->second;
}
}
rhi::ShaderDesc desc;
desc.vsData = vsData;
desc.vsSize = vsSize;
desc.fsData = fsData;
desc.fsSize = fsSize;
rhi::ShaderHandle handle = device.createShader(desc);
// Store in cache
{
std::unique_lock lock(m_mutex);
m_shaders[name] = handle;
}
return handle;
}
bool ResourceCache::hasTexture(const std::string& path) const {
std::shared_lock lock(m_mutex);
return m_textures.find(path) != m_textures.end();
}
bool ResourceCache::hasShader(const std::string& name) const {
std::shared_lock lock(m_mutex);
return m_shaders.find(name) != m_shaders.end();
}
void ResourceCache::clear(rhi::IRHIDevice& device) {
std::unique_lock lock(m_mutex);
for (auto& [path, handle] : m_textures) {
device.destroy(handle);
}
m_textures.clear();
for (auto& [name, handle] : m_shaders) {
device.destroy(handle);
}
m_shaders.clear();
}
size_t ResourceCache::getTextureCount() const {
std::shared_lock lock(m_mutex);
return m_textures.size();
}
size_t ResourceCache::getShaderCount() const {
std::shared_lock lock(m_mutex);
return m_shaders.size();
}
} // namespace grove