112 lines
3.7 KiB
C++
112 lines
3.7 KiB
C++
#include <stb_image.h>
|
|
|
|
#include <sophia/resource_registry_ref.hpp>
|
|
#include <sophia/util/assert.hpp>
|
|
#include <sophia/util/logger.hpp>
|
|
#include <stdexcept>
|
|
|
|
#include "resources/resource_registry.hpp"
|
|
|
|
namespace sophia {
|
|
|
|
template <>
|
|
MeshHandle ResourceRegistryRef::load<Mesh>(const std::string& path) {
|
|
(void)path;
|
|
SOPHIA_ASSERT(false,
|
|
"Mesh::load(path) is not implemented yet - no model file "
|
|
"format is supported; build a MeshData instead");
|
|
return MeshHandle{};
|
|
}
|
|
|
|
template <>
|
|
TextureHandle ResourceRegistryRef::load<Texture>(const std::string& path) {
|
|
int width = 0;
|
|
int height = 0;
|
|
int channels = 0;
|
|
// Always decode to RGBA8, whatever the file has.
|
|
stbi_uc* pixels = stbi_load(path.c_str(), &width, &height, &channels, 4);
|
|
if (pixels == nullptr) {
|
|
log::fatal("failed to load texture {} - {}", path, stbi_failure_reason());
|
|
throw std::runtime_error("failed to load texture: " + path);
|
|
}
|
|
|
|
auto size = static_cast<size_t>(width) * static_cast<size_t>(height) * 4;
|
|
TextureHandle handle = registry->texturePool.create(
|
|
registry->device, static_cast<u32>(width), static_cast<u32>(height),
|
|
std::span<const u8>{pixels, size});
|
|
stbi_image_free(pixels);
|
|
return handle;
|
|
}
|
|
|
|
template <>
|
|
void ResourceRegistryRef::release<Mesh>(MeshHandle handle) {
|
|
// Frames in flight may still be drawing it.
|
|
registry->device.waitIdle();
|
|
registry->meshPool.release(handle);
|
|
}
|
|
|
|
template <>
|
|
void ResourceRegistryRef::release<RenderTarget>(RenderTargetHandle handle) {
|
|
registry->renderTargetPool.release(handle);
|
|
}
|
|
|
|
template <>
|
|
void ResourceRegistryRef::release<Texture>(TextureHandle handle) {
|
|
SOPHIA_ASSERT(handle != registry->whiteTexture,
|
|
"the built-in white texture cannot be released");
|
|
// Frames in flight may still be sampling it.
|
|
registry->device.waitIdle();
|
|
registry->texturePool.release(handle);
|
|
}
|
|
|
|
MeshHandle ResourceRegistryRef::createResource(std::type_identity<Mesh>,
|
|
const MeshData& data) {
|
|
return registry->meshPool.create(registry->device, data);
|
|
}
|
|
|
|
RenderTargetHandle ResourceRegistryRef::createResource(
|
|
std::type_identity<RenderTarget>, u32 width, u32 height) {
|
|
return registry->renderTargetPool.create(width, height);
|
|
}
|
|
|
|
TextureHandle ResourceRegistryRef::createResource(std::type_identity<Texture>,
|
|
u32 width, u32 height,
|
|
std::vector<u8> pixels) {
|
|
return registry->texturePool.create(registry->device, width, height,
|
|
std::span<const u8>{pixels});
|
|
}
|
|
|
|
void ResourceRegistryRef::requestResize(RenderTargetHandle handle, u32 width,
|
|
u32 height) {
|
|
registry->renderTargetPool.get(handle).requestResize(width, height);
|
|
}
|
|
|
|
glm::vec2 ResourceRegistryRef::getExtent(RenderTargetHandle handle) const {
|
|
vk::Extent2D extent = registry->renderTargetPool.get(handle).getExtent();
|
|
return {static_cast<float>(extent.width), static_cast<float>(extent.height)};
|
|
}
|
|
|
|
AABB ResourceRegistryRef::getBounds(MeshHandle handle) const {
|
|
return registry->meshPool.get(handle).getBounds();
|
|
}
|
|
|
|
bool ResourceRegistryRef::isAlive(MeshHandle handle) const {
|
|
return registry->meshPool.isAlive(handle);
|
|
}
|
|
|
|
bool ResourceRegistryRef::isAlive(RenderTargetHandle handle) const {
|
|
return registry->renderTargetPool.isAlive(handle);
|
|
}
|
|
|
|
glm::vec2 ResourceRegistryRef::getExtent(TextureHandle handle) const {
|
|
const Texture& texture = registry->texturePool.get(handle);
|
|
return {static_cast<float>(texture.getWidth()),
|
|
static_cast<float>(texture.getHeight())};
|
|
}
|
|
|
|
bool ResourceRegistryRef::isAlive(TextureHandle handle) const {
|
|
return registry->texturePool.isAlive(handle);
|
|
}
|
|
|
|
} // namespace sophia
|