We be kinda rendering

This commit is contained in:
2026-01-05 06:20:49 +01:00
parent 1168f9e5d1
commit c83c423b42
48 changed files with 2789 additions and 382 deletions

View File

@@ -8,6 +8,7 @@
#include <SDL2/SDL.h>
#include <destrum/Graphics/GfxDevice.h>
#include <destrum/Graphics/Renderer.h>
class App {
@@ -20,6 +21,8 @@ public:
std::filesystem::path exeDir;
};
App();
void init(const AppParams& params);
void run();
void cleanup();
@@ -28,7 +31,15 @@ protected:
SDL_Window* window{nullptr};
AppParams m_params{};
CPUMesh testMesh{};
MeshID testMeshID;
GfxDevice gfxDevice;
GameRenderer renderer;
Camera camera{glm::vec3(0.f, 0.f, -5.f), glm::vec3(0, 1, 0)};
MeshCache meshCache;
bool isRunning{false};
bool gamePaused{false};

View File

@@ -0,0 +1,158 @@
#ifndef VCAMERA_H
#define VCAMERA_H
#include <glm/glm.hpp>
class Camera {
public:
struct Frustum {
glm::vec4 planes[6]; // left, right, bottom, top, near, far
void update(const glm::mat4& vpMatrix) {
// Extract frustum planes from VP matrix (row-major, GLM style)
glm::mat4 m = vpMatrix;
// Left
planes[0] = glm::vec4(
m[0][3] + m[0][0],
m[1][3] + m[1][0],
m[2][3] + m[2][0],
m[3][3] + m[3][0]
);
// Right
planes[1] = glm::vec4(
m[0][3] - m[0][0],
m[1][3] - m[1][0],
m[2][3] - m[2][0],
m[3][3] - m[3][0]
);
// Bottom
planes[2] = glm::vec4(
m[0][3] + m[0][1],
m[1][3] + m[1][1],
m[2][3] + m[2][1],
m[3][3] + m[3][1]
);
// Top
planes[3] = glm::vec4(
m[0][3] - m[0][1],
m[1][3] - m[1][1],
m[2][3] - m[2][1],
m[3][3] - m[3][1]
);
// Near
planes[4] = glm::vec4(
m[0][3] + m[0][2],
m[1][3] + m[1][2],
m[2][3] + m[2][2],
m[3][3] + m[3][2]
);
// Far
planes[5] = glm::vec4(
m[0][3] - m[0][2],
m[1][3] - m[1][2],
m[2][3] - m[2][2],
m[3][3] - m[3][2]
);
// Normalize all planes
for (auto& plane: planes) {
float length = glm::length(glm::vec3(plane));
plane /= length;
}
}
// Fast AABB-Frustum test
// [[nodiscard]] bool isBoxVisible(const AABB& box) const {
// for (const auto& plane: planes) {
// glm::vec3 positive = box.min;
// if (plane.x >= 0) positive.x = box.max.x;
// if (plane.y >= 0) positive.y = box.max.y;
// if (plane.z >= 0) positive.z = box.max.z;
//
// if (glm::dot(glm::vec3(plane), positive) + plane.w < 0) {
// return false;
// }
// }
// return true;
// }
};
explicit Camera(const glm::vec3& position, const glm::vec3& up);
void Update(float deltaTime);
void CalculateViewMatrix();
void CalculateProjectionMatrix();
[[nodiscard]] glm::mat4 GetViewMatrix() const { return m_viewMatrix; }
[[nodiscard]] glm::mat4 GetProjectionMatrix() const { return m_projectionMatrix; }
[[nodiscard]] glm::mat4 GetViewProjectionMatrix() const { return m_projectionMatrix * m_viewMatrix; }
void setAspectRatio(float aspectRatio) {
m_aspectRatio = aspectRatio;
this->CalculateViewMatrix();
this->CalculateProjectionMatrix();
}
glm::vec3 m_position{2.f, 0, 0};
void Translate(const glm::vec3& translation) {
m_position += translation;
}
void SetTarget(const glm::vec3& target);
void ClearTarget();
void Target(const glm::vec3& target);
[[nodiscard]] glm::vec3 GetTarget() const { return m_target; }
[[nodiscard]] bool IsTargetting() const { return m_useTarget; }
[[nodiscard]] const Frustum& GetFrustum() const { return m_frustum; }
[[nodiscard]] glm::vec3 GetPosition() const { return m_position; }
[[nodiscard]] glm::vec3 GetForward() const { return m_forward; }
[[nodiscard]] glm::vec3 GetUp() const { return m_up; }
[[nodiscard]] glm::vec3 GetRight() const { return m_right; }
void SetMovementSpeed(float speed) { m_movementSpeed = speed; }
[[nodiscard]] float GetMovementSpeed() const { return m_movementSpeed; }
private:
float fovAngle{90.f};
float fov{tanf(glm::radians(fovAngle) / 2.f)};
glm::vec3 m_forward{1, 0, 0};
glm::vec3 m_up{0, 1, 0};
glm::vec3 m_right{0, 0, 1};
glm::vec3 m_target{0.0f, 0.0f, 0.0f};
bool m_useTarget{false};
float totalPitch{0.0f};
float totalYaw{0.0f};
glm::mat4 m_viewMatrix{};
glm::mat4 m_invMatrix{};
glm::mat4 m_projectionMatrix{};
float m_aspectRatio{};
float m_cameraSpeed{};
float m_cameraSensitivity{};
float m_zNear{0.001f};
float m_zFar{1000.0f};
float m_iso{100.f};
float m_aperture{2.8f};
float m_shutterSpeed{1.f / 60.f};
float m_scrollSpeed = 2.0f;
Frustum m_frustum{};
float m_movementSpeed{2.0f};
};
#endif //VCAMERA_H

View File

@@ -1,5 +1,5 @@
#ifndef VIMAGE_H
#define VIMAGE_H
#ifndef GPUIMAGE_H
#define GPUIMAGE_H
#include <cstdint>
#include <string>
@@ -7,29 +7,9 @@
#include <vk_mem_alloc.h>
#include <glm/glm.hpp>
class VImage {
public:
glm::ivec2 getSize2D() const { return glm::ivec2{extent.width, extent.height}; }
VkExtent2D getExtent2D() const { return VkExtent2D{extent.width, extent.height}; }
#include <destrum/Graphics/ids.h>
std::uint32_t getBindlessId() const
{
assert(id != NULL_BINDLESS_ID && "Image wasn't added to bindless set");
return id;
}
void setBindlessId(const std::uint32_t id)
{
assert(id != NULL_BINDLESS_ID);
this->id = id;
}
bool isInitialized() const { return id != NULL_BINDLESS_ID; }
VkImage getImage() const { return image; }
VkImageView getImageView() const { return imageView; }
VmaAllocation getAllocation() const { return allocation; }
private:
struct GPUImage {
VkImage image;
VkImageView imageView;
VmaAllocation allocation;
@@ -38,11 +18,29 @@ private:
VkExtent3D extent;
std::uint32_t mipLevels{1};
std::uint32_t numLayers{1};
bool isCubemap{false};
std::string debugName{};
[[nodiscard]] glm::ivec2 getSize2D() const { return glm::ivec2{extent.width, extent.height}; }
[[nodiscard]] VkExtent2D getExtent2D() const { return VkExtent2D{extent.width, extent.height}; }
[[nodiscard]] BindlessID getBindlessId() const
{
assert(id != NULL_BINDLESS_ID && "Image wasn't added to bindless set");
return id;
}
// should be called by ImageCache only
void setBindlessId(const std::uint32_t id)
{
assert(id != NULL_BINDLESS_ID);
this->id = id;
}
[[nodiscard]] bool isInitialized() const { return id != NULL_BINDLESS_ID; }
private:
std::uint32_t id{NULL_BINDLESS_ID}; // bindless id - always equals to ImageId
static const auto NULL_BINDLESS_ID = std::numeric_limits<std::uint32_t>::max();
};
#endif //VIMAGE_H
#endif //GPUIMAGE_H

View File

@@ -6,20 +6,25 @@
#include <SDL.h>
#include <destrum/Graphics/VImage.h>
#include <destrum/Graphics/GPUImage.h>
#include <destrum/Graphics/Swapchain.h>
#include <destrum/Graphics/ImageCache.h>
#include <vulkan/vulkan.h>
#include <volk.h>
#include <VkBootstrap.h>
#include <vk_mem_alloc.h>
#include <filesystem>
#include <optional>
#include "ImmediateExecuter.h"
#include <destrum/Graphics/Swapchain.h>
using ImageId = std::uint32_t;
static const auto NULL_IMAGE_ID = std::numeric_limits<std::uint32_t>::max();
#include <destrum/Graphics/Resources/Buffer.h>
#include <destrum/Graphics/ids.h>
#include "Util.h"
namespace {
using ImmediateExecuteFunction = std::function<void(VkCommandBuffer)>;
@@ -40,14 +45,14 @@ public:
void recreateSwapchain(int width, int height);
VkCommandBuffer beginFrame();
bool needsSwapchainRecreate() const { return swapchain.isDirty(); }
[[nodiscard]] bool needsSwapchainRecreate() const { return swapchain.isDirty(); }
struct EndFrameProps {
const VkClearColorValue clearColor{ {0.f, 0.f, 0.f, 1.f} };
glm::ivec4 drawImageBlitRect{}; // where to blit draw image to
};
void endFrame(VkCommandBuffer cmd, const VImage& drawImage, const EndFrameProps& props);
void endFrame(VkCommandBuffer cmd, const GPUImage& drawImage, const EndFrameProps& props);
void cleanup();
void waitIdle();
@@ -67,6 +72,29 @@ public:
VkExtent2D getSwapchainExtent() const { return swapchain.getExtent(); }
[[nodiscard]] GPUBuffer createBuffer(
std::size_t allocSize,
VkBufferUsageFlags usage,
VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO) const;
[[nodiscard]] VkDeviceAddress getBufferAddress(const GPUBuffer& buffer) const;
void destroyBuffer(const GPUBuffer& buffer) const;
VmaAllocator getAllocator() const { return allocator; }
ImageID createImage(const vkutil::CreateImageInfo& createInfo, const std::string& debugName = "", void* pixelData = nullptr, ImageID imageId = NULL_IMAGE_ID);
ImageID createDrawImage(VkFormat format, glm::ivec2 size, const std::string& debugName = "", ImageID imageId = NULL_IMAGE_ID);
ImageID loadImageFromFile(const std::filesystem::path& path, VkFormat format = VK_FORMAT_R8G8B8A8_SRGB, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, bool mipMap = false);
ImageID addImageToCache(GPUImage image);
const GPUImage& getImage(ImageID id) const;
void uploadImageData(const GPUImage& image, void* pixelData, std::uint32_t layer = 0) const;
GPUImage createImageRaw(const vkutil::CreateImageInfo& createInfo, std::optional<VmaAllocationCreateInfo> customAllocationCreateInfo = std::nullopt) const;
GPUImage loadImageFromFileRaw(const std::filesystem::path& path, VkFormat format, VkImageUsageFlags usage, bool mipMap) const;
void destroyImage(const GPUImage& image) const;
private:
vkb::Instance instance;
@@ -86,8 +114,11 @@ private:
VulkanImmediateExecutor executor;
ImageId whiteImageId{NULL_IMAGE_ID};
ImageId errorImageId{NULL_IMAGE_ID};
ImageID whiteImageId{NULL_IMAGE_ID};
ImageID errorImageId{NULL_IMAGE_ID};
ImageCache imageCache;
};

View File

@@ -0,0 +1,56 @@
#ifndef IMAGECACHE_H
#define IMAGECACHE_H
#pragma once
#include <filesystem>
#include <unordered_map>
#include <vector>
#include <destrum/Graphics/ids.h>
#include <destrum/Graphics/GPUImage.h>
// #include <destrum/Graphics/Vulkan/BindlessSetManager.h>
class GfxDevice;
class ImageCache {
friend class ResourcesInspector;
public:
ImageCache(GfxDevice& gfxDevice);
ImageID loadImageFromFile(
const std::filesystem::path& path,
VkFormat format,
VkImageUsageFlags usage,
bool mipMap);
ImageID addImage(GPUImage image);
ImageID addImage(ImageID id, GPUImage image);
const GPUImage& getImage(ImageID id) const;
ImageID getFreeImageId() const;
void destroyImages();
// BindlessSetManager bindlessSetManager;
void setErrorImageId(ImageID id) { errorImageId = id; }
private:
std::vector<GPUImage> images;
GfxDevice& gfxDevice;
struct LoadedImageInfo {
std::filesystem::path path;
VkFormat format;
VkImageUsageFlags usage;
bool mipMap;
};
std::unordered_map<ImageID, LoadedImageInfo> loadedImagesInfo;
ImageID errorImageId{NULL_IMAGE_ID};
};
#endif //IMAGECACHE_H

View File

@@ -0,0 +1,30 @@
#ifndef MATERIAL_H
#define MATERIAL_H
#include <string>
#include <glm/glm.hpp>
struct MaterialData {
glm::vec3 baseColor;
glm::vec4 metalRoughnessEmissive;
std::uint32_t diffuseTex;
std::uint32_t normalTex;
std::uint32_t metallicRoughnessTex;
std::uint32_t emissiveTex;
};
struct Material {
glm::vec3 baseColor{1.f, 1.f, 1.f};
float metallicFactor{0.f};
float roughnessFactor{0.7f};
float emissiveFactor{0.f};
ImageID diffuseTexture{NULL_IMAGE_ID};
// ImageId normalMapTexture{NULL_IMAGE_ID};
// ImageId metallicRoughnessTexture{NULL_IMAGE_ID};
// ImageId emissiveTexture{NULL_IMAGE_ID};
std::string name;
};
#endif //MATERIAL_H

View File

@@ -0,0 +1,42 @@
#ifndef MATERIALCACHE_H
#define MATERIALCACHE_H
#include <vector>
#include <destrum/Graphics/ids.h>
#include <destrum/Graphics/Material.h>
#include <destrum/Graphics/Resources/Buffer.h>
class GfxDevice;
class MaterialCache {
friend class ResourcesInspector;
public:
void init(GfxDevice& gfxDevice);
void cleanup(GfxDevice& gfxDevice);
MaterialId addMaterial(GfxDevice& gfxDevice, Material material);
const Material& getMaterial(MaterialId id) const;
MaterialId getFreeMaterialId() const;
MaterialId getPlaceholderMaterialId() const;
const GPUBuffer& getMaterialDataBuffer() const { return materialDataBuffer; }
VkDeviceAddress getMaterialDataBufferAddress() const { return materialDataBuffer.address; }
private:
std::vector<Material> materials;
static const auto MAX_MATERIALS = 1000;
GPUBuffer materialDataBuffer;
// material which is used for meshes without materials
MaterialId placeholderMaterialId{NULL_MATERIAL_ID};
ImageID defaultNormalMapTextureID{NULL_IMAGE_ID};
};
#endif //MATERIALCACHE_H

View File

@@ -1,4 +1,23 @@
#ifndef MESHCACHE_H
#define MESHCACHE_H
#include <destrum/Graphics/Resources/Mesh.h>
#include "ids.h"
class GfxDevice;
class MeshCache {
public:
void cleanup(const GfxDevice& gfxDevice);
MeshID addMesh(GfxDevice& gfxDevice, const CPUMesh& cpuMesh);
const GPUMesh& getMesh(MeshID id) const;
private:
void uploadMesh(GfxDevice& gfxDevice, const CPUMesh& cpuMesh, GPUMesh& gpuMesh) const;
std::vector<GPUMesh> meshes;
};
#endif //MESHCACHE_H

View File

@@ -0,0 +1,27 @@
#ifndef MESHDRAWCOMMAND_H
#define MESHDRAWCOMMAND_H
#include <glm/mat4x4.hpp>
#include <destrum/Graphics/ids.h>
struct MeshDrawCommand {
MeshID meshId;
glm::mat4 transformMatrix;
// for frustum culling
// math::Sphere worldBoundingSphere;
// If set - mesh will be drawn with overrideMaterialId
// instead of whatever material the mesh has
MaterialId materialId{NULL_MATERIAL_ID};
bool castShadow{true};
// skinned meshes only
// const SkinnedMesh* skinnedMesh{nullptr};
// std::uint32_t jointMatricesStartIndex;
};
#endif //MESHDRAWCOMMAND_H

View File

@@ -5,13 +5,27 @@
#include <memory>
#include <destrum/Graphics/Pipeline.h>
#include <destrum/Graphics/MeshCache.h>
#include <destrum/Graphics/MaterialCache.h>
#include <destrum/Graphics/Camera.h>
#include <destrum/Graphics/Resources/Buffer.h>
#include <destrum/Graphics/MeshDrawCommand.h>
class MeshPipeline {
public:
MeshPipeline();
~MeshPipeline();
void init(GfxDevice& gfxDevice, VkFormat drawImageFormat, VkFormat depthImageFormat);
void draw();
void draw(VkCommandBuffer cmd,
VkExtent2D renderExtent,
const GfxDevice& gfxDevice,
const MeshCache& meshCache,
const MaterialCache& materialCache,
const Camera& camera,
const GPUBuffer& sceneDataBuffer,
const std::vector<MeshDrawCommand>& drawCommands,
const std::vector<std::size_t>& sortedDrawCommands);
private:
@@ -19,6 +33,14 @@ private:
std::unique_ptr<Pipeline> m_pipeline;
struct PushConstants {
glm::mat4 transform;
VkDeviceAddress sceneDataBuffer;
VkDeviceAddress vertexBuffer;
std::uint32_t materialId;
std::uint32_t padding;
};
};
#endif //MESHPIPELINE_H

View File

@@ -1,10 +1,82 @@
#ifndef RENDERER_H
#define RENDERER_H
#include <glm/vec3.hpp>
#include <destrum/Graphics/Camera.h>
#include <destrum/Graphics/Pipelines/MeshPipeline.h>
#include <destrum/Graphics/MeshCache.h>
#include <destrum/Graphics/ids.h>
#include <destrum/Graphics/MeshDrawCommand.h>
#include <destrum/Graphics/Resources/NBuffer.h>
#include <destrum/Graphics/MaterialCache.h>
#include <memory>
class GameRenderer {
public:
struct SceneData {
const Camera& camera;
glm::vec3 ambientColor;
float ambientIntensity;
glm::vec3 fogColor;
float fogDensity;
};
explicit GameRenderer(MeshCache& meshCache);
void init(GfxDevice& gfxDevice, const glm::ivec2& drawImageSize);
void beginDrawing(GfxDevice& gfxDevice);
void endDrawing();
void draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera& camera, const SceneData& sceneData);
void cleanup();
void drawMesh(MeshID id, const glm::mat4& transform, MaterialId materialId);
private:
void createDrawImage(GfxDevice& gfxDevice, const glm::ivec2& drawImageSize, bool firstCreate);
MeshCache& meshCache;
// MaterialCache& materialCache;
std::vector<MeshDrawCommand> meshDrawCommands;
std::vector<std::size_t> sortedMeshDrawCommands;
VkFormat drawImageFormat{VK_FORMAT_R16G16B16A16_SFLOAT};
VkFormat depthImageFormat{VK_FORMAT_D32_SFLOAT};
ImageID drawImageId{NULL_IMAGE_ID};
ImageID depthImageId{NULL_IMAGE_ID};
VkSampleCountFlagBits samples{VK_SAMPLE_COUNT_1_BIT};
struct GPUSceneData {
// camera
glm::mat4 view;
glm::mat4 proj;
glm::mat4 viewProj;
glm::vec4 cameraPos;
// ambient
glm::vec3 ambientColor;
float ambientIntensity;
// fog
glm::vec3 fogColor;
float fogDensity;
VkDeviceAddress materialsBuffer;
};
NBuffer sceneDataBuffer;
MaterialCache materialCache;
std::unique_ptr<MeshPipeline> meshPipeline;
};
#endif //RENDERER_H

View File

@@ -9,6 +9,8 @@
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <destrum/Graphics/Resources/Buffer.h>
struct CPUMesh {
std::vector<std::uint32_t> indices;
@@ -38,15 +40,66 @@ struct GPUMesh {
// AABB
glm::vec3 minPos;
glm::vec3 maxPos;
math::Sphere boundingSphere;
bool hasSkeleton{false};
// skinned meshes only
GPUBuffer skinningDataBuffer;
// math::Sphere boundingSphere;
};
struct SkinnedMesh {
GPUBuffer skinnedVertexBuffer;
static std::vector<CPUMesh::Vertex> vertices = {
// =======================
// +Z (Front)
// =======================
{{-0.5f, -0.5f, 0.5f}, 0.0f, {0, 0, 1}, 0.0f, {1, 0, 0, 1}},
{{ 0.5f, -0.5f, 0.5f}, 1.0f, {0, 0, 1}, 0.0f, {1, 0, 0, 1}},
{{ 0.5f, 0.5f, 0.5f}, 1.0f, {0, 0, 1}, 1.0f, {1, 0, 0, 1}},
{{-0.5f, 0.5f, 0.5f}, 0.0f, {0, 0, 1}, 1.0f, {1, 0, 0, 1}},
// =======================
// -Z (Back)
// =======================
{{ 0.5f, -0.5f, -0.5f}, 0.0f, {0, 0, -1}, 0.0f, {-1, 0, 0, 1}},
{{-0.5f, -0.5f, -0.5f}, 1.0f, {0, 0, -1}, 0.0f, {-1, 0, 0, 1}},
{{-0.5f, 0.5f, -0.5f}, 1.0f, {0, 0, -1}, 1.0f, {-1, 0, 0, 1}},
{{ 0.5f, 0.5f, -0.5f}, 0.0f, {0, 0, -1}, 1.0f, {-1, 0, 0, 1}},
// =======================
// +X (Right)
// =======================
{{ 0.5f, -0.5f, 0.5f}, 0.0f, {1, 0, 0}, 0.0f, {0, 0, -1, 1}},
{{ 0.5f, -0.5f, -0.5f}, 1.0f, {1, 0, 0}, 0.0f, {0, 0, -1, 1}},
{{ 0.5f, 0.5f, -0.5f}, 1.0f, {1, 0, 0}, 1.0f, {0, 0, -1, 1}},
{{ 0.5f, 0.5f, 0.5f}, 0.0f, {1, 0, 0}, 1.0f, {0, 0, -1, 1}},
// =======================
// -X (Left)
// =======================
{{-0.5f, -0.5f, -0.5f}, 0.0f, {-1, 0, 0}, 0.0f, {0, 0, 1, 1}},
{{-0.5f, -0.5f, 0.5f}, 1.0f, {-1, 0, 0}, 0.0f, {0, 0, 1, 1}},
{{-0.5f, 0.5f, 0.5f}, 1.0f, {-1, 0, 0}, 1.0f, {0, 0, 1, 1}},
{{-0.5f, 0.5f, -0.5f}, 0.0f, {-1, 0, 0}, 1.0f, {0, 0, 1, 1}},
// =======================
// +Y (Top)
// =======================
{{-0.5f, 0.5f, 0.5f}, 0.0f, {0, 1, 0}, 0.0f, {1, 0, 0, 1}},
{{ 0.5f, 0.5f, 0.5f}, 1.0f, {0, 1, 0}, 0.0f, {1, 0, 0, 1}},
{{ 0.5f, 0.5f, -0.5f}, 1.0f, {0, 1, 0}, 1.0f, {1, 0, 0, 1}},
{{-0.5f, 0.5f, -0.5f}, 0.0f, {0, 1, 0}, 1.0f, {1, 0, 0, 1}},
// =======================
// -Y (Bottom)
// =======================
{{-0.5f, -0.5f, -0.5f}, 0.0f, {0, -1, 0}, 0.0f, {1, 0, 0, 1}},
{{ 0.5f, -0.5f, -0.5f}, 1.0f, {0, -1, 0}, 0.0f, {1, 0, 0, 1}},
{{ 0.5f, -0.5f, 0.5f}, 1.0f, {0, -1, 0}, 1.0f, {1, 0, 0, 1}},
{{-0.5f, -0.5f, 0.5f}, 0.0f, {0, -1, 0}, 1.0f, {1, 0, 0, 1}},
};
static std::vector<uint32_t> indices = {
0, 1, 2, 2, 3, 0, // Front
4, 5, 6, 6, 7, 4, // Back
8, 9,10, 10,11, 8, // Right
12,13,14, 14,15,12, // Left
16,17,18, 18,19,16, // Top
20,21,22, 22,23,20 // Bottom
};

View File

@@ -0,0 +1,39 @@
#ifndef NBUFFER_H
#define NBUFFER_H
#include <string>
#include <vector>
#include <destrum/Graphics/Resources/Buffer.h>
class GfxDevice;
class NBuffer {
public:
void init(
GfxDevice& gfxDevice,
VkBufferUsageFlags usage,
std::size_t dataSize,
const std::string& debugName = "");
void cleanup(GfxDevice& gfxDevice);
void uploadNewData(
VkCommandBuffer cmd,
std::size_t frameIndex,
void* newData,
std::size_t dataSize,
std::size_t offset = 0,
bool sync = true) const;
const GPUBuffer& getBuffer() const { return gpuBuffer; }
private:
std::size_t framesInFlight{0};
std::size_t gpuBufferSize{0};
std::vector<GPUBuffer> stagingBuffers;
GPUBuffer gpuBuffer;
bool initialized{false};
};
#endif //NBUFFER_H

View File

@@ -1,8 +1,11 @@
#ifndef UTIL_H
#define UTIL_H
#include <filesystem>
#include <vulkan/vulkan.h>
#include "glm/vec4.hpp"
#define VK_CHECK(call) \
do { \
@@ -11,6 +14,18 @@
} while (0)
namespace vkutil {
struct CreateImageInfo {
VkFormat format;
VkImageUsageFlags usage;
VkImageCreateFlags flags;
VkExtent3D extent{};
std::uint32_t numLayers{1};
VkSampleCountFlagBits samples{VK_SAMPLE_COUNT_1_BIT};
VkImageTiling tiling{VK_IMAGE_TILING_OPTIMAL};
bool mipMap{false};
bool isCubemap{false};
};
void transitionImage(
VkCommandBuffer cmd,
VkImage image,
@@ -35,5 +50,32 @@ namespace vkutil {
int destW,
int destH,
VkFilter filter);
void addDebugLabel(VkDevice device, VkImage image, const char* label);
void addDebugLabel(VkDevice device, VkImageView imageView, const char* label);
void addDebugLabel(VkDevice device, VkShaderModule shaderModule, const char* label);
void addDebugLabel(VkDevice device, VkPipeline pipeline, const char* label);
void addDebugLabel(VkDevice device, VkPipelineLayout layout, const char* label);
void addDebugLabel(VkDevice device, VkBuffer buffer, const char* label);
void addDebugLabel(VkDevice device, VkSampler sampler, const char* label);
struct RenderingInfoParams {
VkExtent2D renderExtent;
VkImageView colorImageView{VK_NULL_HANDLE};
std::optional<glm::vec4> colorImageClearValue;
VkImageView depthImageView{VK_NULL_HANDLE};
std::optional<float> depthImageClearValue;
};
struct RenderInfo {
VkRenderingAttachmentInfo colorAttachment;
VkRenderingAttachmentInfo depthAttachment;
VkRenderingInfo renderingInfo;
};
RenderInfo createRenderingInfo(const RenderingInfoParams& params);
VkShaderModule loadShaderModule(const std::filesystem::path& path, VkDevice device);
}
#endif //UTIL_H

View File

@@ -0,0 +1,19 @@
#ifndef IDS_H
#define IDS_H
#include <cstdint>
#include <limits>
using MeshID = std::size_t;
constexpr MeshID NULL_MESH_ID = std::numeric_limits<std::size_t>::max();
using ImageID = std::uint16_t;
constexpr ImageID NULL_IMAGE_ID = std::numeric_limits<std::uint16_t>::max();
using MaterialId = std::uint32_t;
constexpr MaterialId NULL_MATERIAL_ID = std::numeric_limits<std::uint32_t>::max();
using BindlessID = std::uint32_t;
constexpr BindlessID NULL_BINDLESS_ID = std::numeric_limits<std::uint32_t>::max();
#endif //IDS_H

View File

@@ -0,0 +1,36 @@
#ifndef IMAGELOADER_H
#define IMAGELOADER_H
#include <filesystem>
struct ImageData {
ImageData() = default;
~ImageData();
// move only
ImageData(ImageData&& o) = default;
ImageData& operator=(ImageData&& o) = default;
// no copies
ImageData(const ImageData& o) = delete;
ImageData& operator=(const ImageData& o) = delete;
// data
unsigned char* pixels{nullptr};
int width{0};
int height{0};
int channels{0};
// HDR only
float* hdrPixels{nullptr};
bool hdr{false};
int comp{0};
bool shouldSTBFree{false};
};
namespace util {
ImageData loadImage(const std::filesystem::path& p);
}
#endif //IMAGELOADER_H