mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
Make uniform buffers updateable.
This commit is contained in:
parent
bbf582d85f
commit
fa34a8c583
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
|
|
||||||
|
#include <glm/mat4x4.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
@ -22,6 +24,19 @@ namespace engine {
|
|||||||
class Texture;
|
class Texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct RenderData {
|
||||||
|
std::unique_ptr<GFXDevice> gfxdev;
|
||||||
|
gfx::DrawBuffer* drawBuffer = nullptr;
|
||||||
|
/* uniforms for engine globals */
|
||||||
|
const gfx::DescriptorSetLayout* setZeroLayout;
|
||||||
|
const gfx::DescriptorSet* setZero;
|
||||||
|
struct SetZeroBuffer {
|
||||||
|
glm::mat4 proj;
|
||||||
|
glm::vec2 myValue;
|
||||||
|
};
|
||||||
|
gfx::DescriptorBuffer* setZeroBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
class Application {
|
class Application {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -61,17 +76,16 @@ namespace engine {
|
|||||||
|
|
||||||
/* getters */
|
/* getters */
|
||||||
Window* window() { return m_window.get(); }
|
Window* window() { return m_window.get(); }
|
||||||
GFXDevice* gfx() { return m_gfx.get(); }
|
GFXDevice* gfx() { return renderData.gfxdev.get(); }
|
||||||
InputManager* inputManager() { return m_inputManager.get(); }
|
InputManager* inputManager() { return m_inputManager.get(); }
|
||||||
SceneManager* sceneManager() { return m_sceneManager.get(); }
|
SceneManager* sceneManager() { return m_sceneManager.get(); }
|
||||||
|
|
||||||
gfx::DrawBuffer* getDrawBuffer() { return m_drawBuffer; }
|
|
||||||
|
|
||||||
std::string getResourcePath(const std::string relativePath) { return (m_resourcesPath / relativePath).string(); }
|
std::string getResourcePath(const std::string relativePath) { return (m_resourcesPath / relativePath).string(); }
|
||||||
|
|
||||||
|
RenderData renderData{};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Window> m_window;
|
std::unique_ptr<Window> m_window;
|
||||||
std::unique_ptr<GFXDevice> m_gfx;
|
|
||||||
std::unique_ptr<InputManager> m_inputManager;
|
std::unique_ptr<InputManager> m_inputManager;
|
||||||
std::unique_ptr<SceneManager> m_sceneManager;
|
std::unique_ptr<SceneManager> m_sceneManager;
|
||||||
|
|
||||||
@ -79,8 +93,6 @@ namespace engine {
|
|||||||
|
|
||||||
bool m_enableFrameLimiter = true;
|
bool m_enableFrameLimiter = true;
|
||||||
|
|
||||||
gfx::DrawBuffer *m_drawBuffer;
|
|
||||||
|
|
||||||
/* resource stuff */
|
/* resource stuff */
|
||||||
|
|
||||||
std::unordered_map<size_t, std::unique_ptr<IResourceManager>> m_resourceManagers{};
|
std::unordered_map<size_t, std::unique_ptr<IResourceManager>> m_resourceManagers{};
|
||||||
|
@ -9,6 +9,7 @@ namespace engine::gfx {
|
|||||||
|
|
||||||
// handles (incomplete types)
|
// handles (incomplete types)
|
||||||
struct Pipeline;
|
struct Pipeline;
|
||||||
|
struct DescriptorBuffer;
|
||||||
struct Buffer;
|
struct Buffer;
|
||||||
struct Texture;
|
struct Texture;
|
||||||
struct DrawBuffer;
|
struct DrawBuffer;
|
||||||
|
@ -26,9 +26,9 @@ namespace engine {
|
|||||||
void cmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer);
|
void cmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer);
|
||||||
void cmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer);
|
void cmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer);
|
||||||
void cmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
|
void cmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
|
||||||
|
void cmdPushConstants(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, uint32_t offset, uint32_t size, const void* data);
|
||||||
void cmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, const gfx::DescriptorSet* set, uint32_t setNumber);
|
void cmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, const gfx::DescriptorSet* set, uint32_t setNumber);
|
||||||
|
|
||||||
// creates the equivalent of an OpenGL shader program & vertex attrib configuration
|
|
||||||
gfx::Pipeline* createPipeline(const gfx::PipelineInfo& info);
|
gfx::Pipeline* createPipeline(const gfx::PipelineInfo& info);
|
||||||
void destroyPipeline(const gfx::Pipeline* pipeline);
|
void destroyPipeline(const gfx::Pipeline* pipeline);
|
||||||
|
|
||||||
@ -36,11 +36,15 @@ namespace engine {
|
|||||||
void destroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout);
|
void destroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout);
|
||||||
|
|
||||||
gfx::DescriptorSet* allocateDescriptorSet(const gfx::DescriptorSetLayout* layout);
|
gfx::DescriptorSet* allocateDescriptorSet(const gfx::DescriptorSetLayout* layout);
|
||||||
void updateDescriptor(const gfx::DescriptorSet* set, uint32_t binding, const gfx::Buffer* buffer);
|
// This updates all copies of the descriptor. This cannot be used after any frames have been renderered
|
||||||
|
void updateDescriptor(const gfx::DescriptorSet* set, uint32_t binding, const gfx::DescriptorBuffer* buffer, size_t offset, size_t range);
|
||||||
|
|
||||||
void updateUniformBuffer(const gfx::Pipeline* pipeline, const void* data, size_t size, uint32_t offset);
|
gfx::DescriptorBuffer* createDescriptorBuffer(uint64_t size, const void* initialData);
|
||||||
|
void destroyDescriptorBuffer(const gfx::DescriptorBuffer* descriptorBuffer);
|
||||||
|
|
||||||
// Tries to create it on the GPU. Cannot be directly updated by the CPU.
|
void writeDescriptorBuffer(gfx::DescriptorBuffer* buffer, uint64_t offset, uint64_t size, const void* data);
|
||||||
|
|
||||||
|
// Loads data into staging buffer and copies that into a single GPU buffer.
|
||||||
gfx::Buffer* createBuffer(gfx::BufferType type, uint64_t size, const void* data);
|
gfx::Buffer* createBuffer(gfx::BufferType type, uint64_t size, const void* data);
|
||||||
void destroyBuffer(const gfx::Buffer* buffer);
|
void destroyBuffer(const gfx::Buffer* buffer);
|
||||||
|
|
||||||
@ -54,6 +58,8 @@ namespace engine {
|
|||||||
bool useAnisotropy = false);
|
bool useAnisotropy = false);
|
||||||
void destroyTexture(const gfx::Texture* texture);
|
void destroyTexture(const gfx::Texture* texture);
|
||||||
|
|
||||||
|
uint64_t getFrameCount();
|
||||||
|
|
||||||
// wait until all the active GPU queues have finished working
|
// wait until all the active GPU queues have finished working
|
||||||
void waitIdle();
|
void waitIdle();
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
namespace engine {
|
namespace engine {
|
||||||
class GFXDevice;
|
class GFXDevice;
|
||||||
|
struct RenderData;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace engine::resources {
|
namespace engine::resources {
|
||||||
@ -20,20 +21,15 @@ public:
|
|||||||
bool hasUV0; // vec2
|
bool hasUV0; // vec2
|
||||||
};
|
};
|
||||||
|
|
||||||
Shader(GFXDevice* gfx, const char* vertPath, const char* fragPath, const VertexParams& vertexParams, bool alphaBlending, bool cullBackFace);
|
Shader(RenderData* renderData, const char* vertPath, const char* fragPath, const VertexParams& vertexParams, bool alphaBlending, bool cullBackFace);
|
||||||
~Shader();
|
~Shader();
|
||||||
Shader(const Shader&) = delete;
|
Shader(const Shader&) = delete;
|
||||||
Shader& operator=(const Shader&) = delete;
|
Shader& operator=(const Shader&) = delete;
|
||||||
|
|
||||||
const gfx::Pipeline* getPipeline();
|
const gfx::Pipeline* getPipeline();
|
||||||
|
|
||||||
const gfx::DescriptorSet* getSetZero() { return m_setZero; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GFXDevice* const m_gfx;
|
GFXDevice* const m_gfx;
|
||||||
const gfx::DescriptorSetLayout* m_setZeroLayout;
|
|
||||||
const gfx::DescriptorSet* m_setZero;
|
|
||||||
const gfx::Buffer* m_setZeroBuffer;
|
|
||||||
const gfx::Pipeline* m_pipeline;
|
const gfx::Pipeline* m_pipeline;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -7,18 +7,24 @@
|
|||||||
#include "components/transform.hpp"
|
#include "components/transform.hpp"
|
||||||
#include "components/renderable.hpp"
|
#include "components/renderable.hpp"
|
||||||
|
|
||||||
|
#include "gfx.hpp"
|
||||||
|
#include "gfx_device.hpp"
|
||||||
|
|
||||||
namespace engine {
|
namespace engine {
|
||||||
|
|
||||||
class RenderSystem : public System {
|
class RenderSystem : public System {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RenderSystem(Scene* scene);
|
RenderSystem(Scene* scene);
|
||||||
|
~RenderSystem();
|
||||||
|
|
||||||
void onUpdate(float ts) override;
|
void onUpdate(float ts) override;
|
||||||
|
|
||||||
void setCameraEntity(uint32_t entity);
|
void setCameraEntity(uint32_t entity);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
GFXDevice* const m_gfx;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
// only uses transform component, which is required for all entities anyway
|
// only uses transform component, which is required for all entities anyway
|
||||||
uint32_t camEntity = 0;
|
uint32_t camEntity = 0;
|
||||||
@ -29,6 +35,8 @@ namespace engine {
|
|||||||
|
|
||||||
float m_viewportAspectRatio = 1.0f;
|
float m_viewportAspectRatio = 1.0f;
|
||||||
|
|
||||||
|
float m_value = 0.0f;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(binding = 0) uniform UBO {
|
|
||||||
mat4 proj;
|
|
||||||
} ubo;
|
|
||||||
|
|
||||||
layout( push_constant ) uniform Constants {
|
layout( push_constant ) uniform Constants {
|
||||||
mat4 model;
|
mat4 model;
|
||||||
mat4 view;
|
mat4 view;
|
||||||
} constants;
|
} constants;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0) uniform SetZeroBuffer {
|
||||||
|
mat4 proj;
|
||||||
|
vec2 myValue;
|
||||||
|
} setZeroBuffer;
|
||||||
|
|
||||||
layout(location = 0) in vec3 inPosition;
|
layout(location = 0) in vec3 inPosition;
|
||||||
layout(location = 1) in vec3 inNorm;
|
layout(location = 1) in vec3 inNorm;
|
||||||
layout(location = 2) in vec2 inUV;
|
layout(location = 2) in vec2 inUV;
|
||||||
@ -16,6 +17,6 @@ layout(location = 2) in vec2 inUV;
|
|||||||
layout(location = 0) out vec3 fragNorm;
|
layout(location = 0) out vec3 fragNorm;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = ubo.proj * constants.view * constants.model * vec4(inPosition, 1.0);
|
gl_Position = setZeroBuffer.proj * constants.view * constants.model * vec4(inPosition, 1.0);
|
||||||
fragNorm = mat3(transpose(inverse(constants.model))) * inNorm;
|
fragNorm = mat3(transpose(inverse(constants.model))) * inNorm;
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(binding = 0) uniform UBO {
|
|
||||||
mat4 proj;
|
|
||||||
} ubo;
|
|
||||||
|
|
||||||
layout( push_constant ) uniform Constants {
|
layout( push_constant ) uniform Constants {
|
||||||
mat4 model;
|
mat4 model;
|
||||||
mat4 view;
|
mat4 view;
|
||||||
} constants;
|
} constants;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0) uniform SetZeroBuffer {
|
||||||
|
mat4 proj;
|
||||||
|
vec2 myValue;
|
||||||
|
} setZeroBuffer;
|
||||||
|
|
||||||
layout(location = 0) in vec3 inPosition;
|
layout(location = 0) in vec3 inPosition;
|
||||||
layout(location = 1) in vec3 inNorm;
|
layout(location = 1) in vec3 inNorm;
|
||||||
layout(location = 2) in vec2 inUV;
|
layout(location = 2) in vec2 inUV;
|
||||||
@ -16,6 +17,6 @@ layout(location = 2) in vec2 inUV;
|
|||||||
layout(location = 0) out vec2 fragUV;
|
layout(location = 0) out vec2 fragUV;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = ubo.proj * constants.view * constants.model * vec4(inPosition, 1.0);
|
gl_Position = setZeroBuffer.proj * constants.view * constants.model * vec4(inPosition, 1.0);
|
||||||
fragUV = inUV;
|
fragUV = inUV;
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,13 @@ layout(location = 0) in vec2 fragUV;
|
|||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
layout(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
layout(set = 1, binding = 0) uniform sampler2D texSampler;
|
//layout(set = 1, binding = 0) uniform sampler2D texSampler;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
gl_FragDepth = 0.9999;
|
gl_FragDepth = 0.9999;
|
||||||
outColor = texture(texSampler, fragUV);
|
//outColor = texture(texSampler, fragUV);
|
||||||
|
outColor = vec4(0.1, 0.1, 0.1, 1.0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(binding = 0) uniform UBO {
|
|
||||||
mat4 proj;
|
|
||||||
mat4 view;
|
|
||||||
} ubo;
|
|
||||||
|
|
||||||
layout( push_constant ) uniform Constants {
|
layout( push_constant ) uniform Constants {
|
||||||
mat4 model;
|
mat4 model;
|
||||||
mat4 view;
|
mat4 view;
|
||||||
} constants;
|
} constants;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0) uniform SetZeroBuffer {
|
||||||
|
mat4 proj;
|
||||||
|
vec2 myValue;
|
||||||
|
} setZeroBuffer;
|
||||||
|
|
||||||
layout(location = 0) in vec3 inPosition;
|
layout(location = 0) in vec3 inPosition;
|
||||||
layout(location = 2) in vec2 inUV;
|
layout(location = 2) in vec2 inUV;
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ layout(location = 0) out vec2 fragUV;
|
|||||||
void main() {
|
void main() {
|
||||||
mat4 myView = constants.view;
|
mat4 myView = constants.view;
|
||||||
myView[3] = vec4(0.0, 0.0, 0.0, 1.0);
|
myView[3] = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
vec4 pos = ubo.proj * myView * constants.model * vec4(inPosition, 1.0);
|
vec4 pos = setZeroBuffer.proj * myView * constants.model * vec4(inPosition, 1.0);
|
||||||
gl_Position = pos;
|
gl_Position = pos;
|
||||||
fragUV = inUV;
|
fragUV = inUV;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ layout(location = 3) in vec3 fragLightPos;
|
|||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
layout(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
layout(set = 1, binding = 0) uniform sampler2D texSampler;
|
//layout(set = 1, binding = 0) uniform sampler2D texSampler;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
@ -15,7 +15,8 @@ void main() {
|
|||||||
vec3 lightColor = vec3(1.0, 1.0, 1.0);
|
vec3 lightColor = vec3(1.0, 1.0, 1.0);
|
||||||
vec3 ambientColor = vec3(1.0, 1.0, 1.0);
|
vec3 ambientColor = vec3(1.0, 1.0, 1.0);
|
||||||
float ambientStrength = 0.05;
|
float ambientStrength = 0.05;
|
||||||
vec3 baseColor = vec3(texture(texSampler, fragUV));
|
//vec3 baseColor = vec3(texture(texSampler, fragUV));
|
||||||
|
vec3 baseColor = vec3(mod(fragUV.x, 1.0), mod(fragUV.y, 1.0), 0.0);
|
||||||
vec3 emission = vec3(0.0, 0.0, 0.0);
|
vec3 emission = vec3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
// code
|
// code
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform UBO {
|
|
||||||
mat4 proj;
|
|
||||||
mat4 view;
|
|
||||||
} ubo;
|
|
||||||
|
|
||||||
layout( push_constant ) uniform Constants {
|
layout( push_constant ) uniform Constants {
|
||||||
mat4 model;
|
mat4 model;
|
||||||
mat4 view;
|
mat4 view;
|
||||||
} constants;
|
} constants;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0) uniform SetZeroBuffer {
|
||||||
|
mat4 proj;
|
||||||
|
vec2 myValue;
|
||||||
|
} setZeroBuffer;
|
||||||
|
|
||||||
layout(location = 0) in vec3 inPosition;
|
layout(location = 0) in vec3 inPosition;
|
||||||
layout(location = 1) in vec3 inNorm;
|
layout(location = 1) in vec3 inNorm;
|
||||||
layout(location = 2) in vec2 inUV;
|
layout(location = 2) in vec2 inUV;
|
||||||
@ -20,7 +20,7 @@ layout(location = 2) out vec2 fragUV;
|
|||||||
layout(location = 3) out vec3 fragLightPos;
|
layout(location = 3) out vec3 fragLightPos;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = ubo.proj * constants.view * constants.model * vec4(inPosition, 1.0);
|
gl_Position = setZeroBuffer.proj * constants.view * constants.model * vec4(inPosition, 1.0);
|
||||||
|
|
||||||
fragPos = vec3(constants.view * constants.model * vec4(inPosition, 1.0));
|
fragPos = vec3(constants.view * constants.model * vec4(inPosition, 1.0));
|
||||||
fragNorm = mat3(transpose(inverse(constants.view * constants.model))) * inNorm;
|
fragNorm = mat3(transpose(inverse(constants.view * constants.model))) * inNorm;
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
#version 450
|
|
||||||
|
|
||||||
layout(location = 0) in vec2 fragUV;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
vec3 baseColor = vec3(fragUV, 0.0);
|
|
||||||
outColor = vec4(baseColor, 1.0);
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
|||||||
#version 450
|
|
||||||
|
|
||||||
layout(location = 0) in vec3 inPosition;
|
|
||||||
layout(location = 2) in vec2 inUV;
|
|
||||||
|
|
||||||
layout(location = 0) out vec2 fragUV;
|
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform MyUniform {
|
|
||||||
vec4 someValue;
|
|
||||||
} myUniform;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
gl_Position = vec4(inPosition, 1.0);
|
|
||||||
fragUV = inUV * myUniform.someValue.xy;
|
|
||||||
}
|
|
@ -14,6 +14,8 @@
|
|||||||
#include "resources/shader.hpp"
|
#include "resources/shader.hpp"
|
||||||
#include "resources/texture.hpp"
|
#include "resources/texture.hpp"
|
||||||
|
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
// To allow the FPS-limiter to put the thread to sleep
|
// To allow the FPS-limiter to put the thread to sleep
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
@ -23,43 +25,42 @@
|
|||||||
#define MAX_PATH 260
|
#define MAX_PATH 260
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::filesystem::path getResourcesPath()
|
namespace engine {
|
||||||
{
|
|
||||||
std::filesystem::path resourcesPath{};
|
static std::filesystem::path getResourcesPath()
|
||||||
|
{
|
||||||
|
std::filesystem::path resourcesPath{};
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
CHAR exeDirBuf[MAX_PATH + 1];
|
CHAR exeDirBuf[MAX_PATH + 1];
|
||||||
GetModuleFileNameA(NULL, exeDirBuf, MAX_PATH + 1);
|
GetModuleFileNameA(NULL, exeDirBuf, MAX_PATH + 1);
|
||||||
std::filesystem::path cwd = std::filesystem::path(exeDirBuf).parent_path();
|
std::filesystem::path cwd = std::filesystem::path(exeDirBuf).parent_path();
|
||||||
(void)_chdir((const char*)std::filesystem::absolute(cwd).c_str());
|
(void)_chdir((const char*)std::filesystem::absolute(cwd).c_str());
|
||||||
#else
|
#else
|
||||||
std::filesystem::path cwd = std::filesystem::current_path();
|
std::filesystem::path cwd = std::filesystem::current_path();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (std::filesystem::is_directory(cwd / "res")) {
|
if (std::filesystem::is_directory(cwd / "res")) {
|
||||||
resourcesPath = cwd / "res";
|
resourcesPath = cwd / "res";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
resourcesPath = cwd.parent_path() / "share" / "sdltest";
|
resourcesPath = cwd.parent_path() / "share" / "sdltest";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::filesystem::is_directory(resourcesPath) == false) {
|
if (std::filesystem::is_directory(resourcesPath) == false) {
|
||||||
resourcesPath = cwd.root_path() / "usr" / "local" / "share" / "sdltest";
|
resourcesPath = cwd.root_path() / "usr" / "local" / "share" / "sdltest";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::filesystem::is_directory(resourcesPath) == false) {
|
||||||
|
throw std::runtime_error("Unable to determine resources location. CWD: " + cwd.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourcesPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::filesystem::is_directory(resourcesPath) == false) {
|
|
||||||
throw std::runtime_error("Unable to determine resources location. CWD: " + cwd.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
return resourcesPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
Application::Application(const char* appName, const char* appVersion, gfx::GraphicsSettings graphicsSettings)
|
Application::Application(const char* appName, const char* appVersion, gfx::GraphicsSettings graphicsSettings)
|
||||||
{
|
{
|
||||||
m_window = std::make_unique<Window>(appName, true, false);
|
m_window = std::make_unique<Window>(appName, true, false);
|
||||||
m_gfx = std::make_unique<GFXDevice>(appName, appVersion, m_window->getHandle(), graphicsSettings);
|
|
||||||
m_inputManager = std::make_unique<InputManager>(window());
|
m_inputManager = std::make_unique<InputManager>(window());
|
||||||
m_sceneManager = std::make_unique<SceneManager>(this);
|
m_sceneManager = std::make_unique<SceneManager>(this);
|
||||||
|
|
||||||
@ -72,14 +73,24 @@ namespace engine {
|
|||||||
registerResourceManager<resources::Material>();
|
registerResourceManager<resources::Material>();
|
||||||
registerResourceManager<resources::Mesh>();
|
registerResourceManager<resources::Mesh>();
|
||||||
|
|
||||||
|
// initialise the render data
|
||||||
|
renderData.gfxdev = std::make_unique<GFXDevice>(appName, appVersion, m_window->getHandle(), graphicsSettings);
|
||||||
|
renderData.setZeroLayout = gfx()->createDescriptorSetLayout();
|
||||||
|
renderData.setZero = gfx()->allocateDescriptorSet(renderData.setZeroLayout);
|
||||||
|
RenderData::SetZeroBuffer initialData{
|
||||||
|
.proj = glm::perspectiveZO(glm::radians(70.0f), 1024.0f / 768.0f, 0.1f, 1000.0f),
|
||||||
|
.myValue = { 0.0f, 1.0f }
|
||||||
|
};
|
||||||
|
renderData.setZeroBuffer = gfx()->createDescriptorBuffer(sizeof(RenderData::SetZeroBuffer), &initialData);
|
||||||
|
gfx()->updateDescriptor(renderData.setZero, 0, renderData.setZeroBuffer, 0, sizeof(RenderData::SetZeroBuffer));
|
||||||
|
|
||||||
// default resources
|
// default resources
|
||||||
#if 0
|
|
||||||
{
|
{
|
||||||
resources::Shader::VertexParams vertParams{};
|
resources::Shader::VertexParams vertParams{};
|
||||||
vertParams.hasNormal = true;
|
vertParams.hasNormal = true;
|
||||||
vertParams.hasUV0 = true;
|
vertParams.hasUV0 = true;
|
||||||
auto texturedShader = std::make_unique<resources::Shader>(
|
auto texturedShader = std::make_unique<resources::Shader>(
|
||||||
gfx(),
|
&renderData,
|
||||||
getResourcePath("engine/shaders/standard.vert").c_str(),
|
getResourcePath("engine/shaders/standard.vert").c_str(),
|
||||||
getResourcePath("engine/shaders/standard.frag").c_str(),
|
getResourcePath("engine/shaders/standard.frag").c_str(),
|
||||||
vertParams,
|
vertParams,
|
||||||
@ -93,7 +104,7 @@ namespace engine {
|
|||||||
vertParams.hasNormal = true;
|
vertParams.hasNormal = true;
|
||||||
vertParams.hasUV0 = true;
|
vertParams.hasUV0 = true;
|
||||||
auto texturedShader = std::make_unique<resources::Shader>(
|
auto texturedShader = std::make_unique<resources::Shader>(
|
||||||
gfx(),
|
&renderData,
|
||||||
getResourcePath("engine/shaders/skybox.vert").c_str(),
|
getResourcePath("engine/shaders/skybox.vert").c_str(),
|
||||||
getResourcePath("engine/shaders/skybox.frag").c_str(),
|
getResourcePath("engine/shaders/skybox.frag").c_str(),
|
||||||
vertParams,
|
vertParams,
|
||||||
@ -102,7 +113,6 @@ namespace engine {
|
|||||||
);
|
);
|
||||||
getResourceManager<resources::Shader>()->addPersistent("builtin.skybox", std::move(texturedShader));
|
getResourceManager<resources::Shader>()->addPersistent("builtin.skybox", std::move(texturedShader));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
auto whiteTexture = std::make_unique<resources::Texture>(
|
auto whiteTexture = std::make_unique<resources::Texture>(
|
||||||
gfx(),
|
gfx(),
|
||||||
@ -115,7 +125,11 @@ namespace engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application() {}
|
Application::~Application()
|
||||||
|
{
|
||||||
|
gfx()->destroyDescriptorBuffer(renderData.setZeroBuffer);
|
||||||
|
gfx()->destroyDescriptorSetLayout(renderData.setZeroLayout);
|
||||||
|
}
|
||||||
|
|
||||||
void Application::gameLoop()
|
void Application::gameLoop()
|
||||||
{
|
{
|
||||||
@ -132,7 +146,7 @@ namespace engine {
|
|||||||
while (m_window->isRunning()) {
|
while (m_window->isRunning()) {
|
||||||
|
|
||||||
/* begin rendering */
|
/* begin rendering */
|
||||||
m_drawBuffer = m_gfx->beginRender();
|
renderData.drawBuffer = gfx()->beginRender();
|
||||||
|
|
||||||
/* logic */
|
/* logic */
|
||||||
m_sceneManager->updateActiveScene(m_window->dt());
|
m_sceneManager->updateActiveScene(m_window->dt());
|
||||||
@ -149,7 +163,7 @@ namespace engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* draw */
|
/* draw */
|
||||||
m_gfx->finishRender(m_drawBuffer);
|
gfx()->finishRender(renderData.drawBuffer);
|
||||||
|
|
||||||
/* poll events */
|
/* poll events */
|
||||||
m_window->getInputAndEvents();
|
m_window->getInputAndEvents();
|
||||||
@ -163,7 +177,7 @@ namespace engine {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_gfx->waitIdle();
|
gfx()->waitIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <queue>
|
#include <deque>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@ -61,6 +61,7 @@ namespace engine {
|
|||||||
VkBuffer buffer = VK_NULL_HANDLE;
|
VkBuffer buffer = VK_NULL_HANDLE;
|
||||||
VmaAllocation allocation = nullptr;
|
VmaAllocation allocation = nullptr;
|
||||||
VkDeviceSize size = 0;
|
VkDeviceSize size = 0;
|
||||||
|
bool hostVisible = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gfx::Pipeline {
|
struct gfx::Pipeline {
|
||||||
@ -80,6 +81,7 @@ namespace engine {
|
|||||||
|
|
||||||
struct gfx::DrawBuffer {
|
struct gfx::DrawBuffer {
|
||||||
FrameData frameData;
|
FrameData frameData;
|
||||||
|
uint32_t currentFrameIndex; // corresponds to the frameData
|
||||||
uint32_t imageIndex; // for swapchain present
|
uint32_t imageIndex; // for swapchain present
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -88,7 +90,12 @@ namespace engine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct gfx::DescriptorSet {
|
struct gfx::DescriptorSet {
|
||||||
VkDescriptorSet set;
|
std::array<VkDescriptorSet, FRAMES_IN_FLIGHT> sets; // frames in flight cannot use the same descriptor set in case the buffer needs updating
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gfx::DescriptorBuffer {
|
||||||
|
gfx::Buffer stagingBuffer{};
|
||||||
|
std::array<gfx::Buffer, FRAMES_IN_FLIGHT> gpuBuffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
// enum converters
|
// enum converters
|
||||||
@ -552,6 +559,7 @@ namespace engine {
|
|||||||
Swapchain swapchain{};
|
Swapchain swapchain{};
|
||||||
|
|
||||||
VkDescriptorPool descriptorPool;
|
VkDescriptorPool descriptorPool;
|
||||||
|
std::array<std::unordered_set<gfx::DescriptorBuffer*>, FRAMES_IN_FLIGHT> descriptorBufferWriteQueues{};
|
||||||
|
|
||||||
uint64_t FRAMECOUNT = 0;
|
uint64_t FRAMECOUNT = 0;
|
||||||
|
|
||||||
@ -696,9 +704,17 @@ namespace engine {
|
|||||||
{
|
{
|
||||||
VkResult res;
|
VkResult res;
|
||||||
|
|
||||||
uint32_t swapchainImageIndex;
|
const uint32_t currentFrameIndex = pimpl->FRAMECOUNT % FRAMES_IN_FLIGHT;
|
||||||
|
const FrameData frameData = pimpl->frameData[currentFrameIndex];
|
||||||
|
|
||||||
FrameData frameData = pimpl->frameData[pimpl->FRAMECOUNT % FRAMES_IN_FLIGHT];
|
/* first empty the descriptor buffer write queue */
|
||||||
|
auto& writeQueue = pimpl->descriptorBufferWriteQueues[currentFrameIndex];
|
||||||
|
for (gfx::DescriptorBuffer* buffer : writeQueue) {
|
||||||
|
copyBuffer(pimpl->device.device, pimpl->device.commandPools.transfer, pimpl->device.queues.transferQueues[0], buffer->stagingBuffer.buffer, buffer->gpuBuffers[currentFrameIndex].buffer, buffer->stagingBuffer.size);
|
||||||
|
}
|
||||||
|
writeQueue.clear();
|
||||||
|
|
||||||
|
uint32_t swapchainImageIndex;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (pimpl->swapchainIsOutOfDate) {
|
if (pimpl->swapchainIsOutOfDate) {
|
||||||
@ -736,10 +752,10 @@ namespace engine {
|
|||||||
|
|
||||||
{ // RECORDING
|
{ // RECORDING
|
||||||
|
|
||||||
VkClearValue clearValue{};
|
VkClearValue clearValue{}; // Using same value for all components enables compression according to NVIDIA Best Practices
|
||||||
clearValue.color.float32[0] = 1.0f;
|
clearValue.color.float32[0] = 1.0f;
|
||||||
clearValue.color.float32[1] = 0.0f;
|
clearValue.color.float32[1] = 1.0f;
|
||||||
clearValue.color.float32[2] = 0.0f;
|
clearValue.color.float32[2] = 1.0f;
|
||||||
clearValue.color.float32[3] = 1.0f;
|
clearValue.color.float32[3] = 1.0f;
|
||||||
|
|
||||||
VkRenderPassBeginInfo passBegin{
|
VkRenderPassBeginInfo passBegin{
|
||||||
@ -773,6 +789,7 @@ namespace engine {
|
|||||||
// hand command buffer over to caller
|
// hand command buffer over to caller
|
||||||
gfx::DrawBuffer* drawBuffer = new gfx::DrawBuffer;
|
gfx::DrawBuffer* drawBuffer = new gfx::DrawBuffer;
|
||||||
drawBuffer->frameData = frameData;
|
drawBuffer->frameData = frameData;
|
||||||
|
drawBuffer->currentFrameIndex = currentFrameIndex;
|
||||||
drawBuffer->imageIndex = swapchainImageIndex;
|
drawBuffer->imageIndex = swapchainImageIndex;
|
||||||
return drawBuffer;
|
return drawBuffer;
|
||||||
|
|
||||||
@ -862,9 +879,15 @@ namespace engine {
|
|||||||
vkCmdDrawIndexed(drawBuffer->frameData.drawBuf, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
|
vkCmdDrawIndexed(drawBuffer->frameData.drawBuf, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GFXDevice::cmdPushConstants(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, uint32_t offset, uint32_t size, const void* data)
|
||||||
|
{
|
||||||
|
assert(drawBuffer != nullptr);
|
||||||
|
vkCmdPushConstants(drawBuffer->frameData.drawBuf, pipeline->layout, VK_SHADER_STAGE_VERTEX_BIT, offset, size, data);
|
||||||
|
}
|
||||||
|
|
||||||
void GFXDevice::cmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, const gfx::DescriptorSet* set, uint32_t setNumber)
|
void GFXDevice::cmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, const gfx::DescriptorSet* set, uint32_t setNumber)
|
||||||
{
|
{
|
||||||
vkCmdBindDescriptorSets(drawBuffer->frameData.drawBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->layout, setNumber, 1, &set->set, 0, nullptr);
|
vkCmdBindDescriptorSets(drawBuffer->frameData.drawBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->layout, setNumber, 1, &set->sets[drawBuffer->currentFrameIndex], 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::Pipeline* GFXDevice::createPipeline(const gfx::PipelineInfo& info)
|
gfx::Pipeline* GFXDevice::createPipeline(const gfx::PipelineInfo& info)
|
||||||
@ -1114,61 +1137,133 @@ namespace engine {
|
|||||||
{
|
{
|
||||||
gfx::DescriptorSet* set = new gfx::DescriptorSet{};
|
gfx::DescriptorSet* set = new gfx::DescriptorSet{};
|
||||||
|
|
||||||
VkDescriptorSetAllocateInfo allocInfo{
|
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
||||||
|
VkDescriptorSetAllocateInfo allocInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.descriptorPool = pimpl->descriptorPool,
|
.descriptorPool = pimpl->descriptorPool,
|
||||||
.descriptorSetCount = 1,
|
.descriptorSetCount = 1,
|
||||||
.pSetLayouts = &layout->layout
|
.pSetLayouts = &layout->layout
|
||||||
};
|
};
|
||||||
|
VkResult res;
|
||||||
VkResult res;
|
res = vkAllocateDescriptorSets(pimpl->device.device, &allocInfo, &set->sets[i]);
|
||||||
res = vkAllocateDescriptorSets(pimpl->device.device, &allocInfo, &set->set);
|
if (res == VK_ERROR_FRAGMENTED_POOL) throw std::runtime_error("Descriptor pool is fragmented!");
|
||||||
if (res == VK_ERROR_FRAGMENTED_POOL) throw std::runtime_error("Descriptor pool is fragmented!");
|
if (res == VK_ERROR_OUT_OF_POOL_MEMORY) throw std::runtime_error("Descriptor pool is out of memory!");
|
||||||
if (res == VK_ERROR_OUT_OF_POOL_MEMORY) throw std::runtime_error("Descriptor pool is out of memory!");
|
VKCHECK(res);
|
||||||
VKCHECK(res);
|
}
|
||||||
|
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::updateDescriptor(const gfx::DescriptorSet* set, uint32_t binding, const gfx::Buffer* buffer)
|
void GFXDevice::updateDescriptor(const gfx::DescriptorSet* set, uint32_t binding, const gfx::DescriptorBuffer* buffer, size_t offset, size_t range)
|
||||||
{
|
{
|
||||||
VkDescriptorBufferInfo bufferInfo{
|
assert(pimpl->FRAMECOUNT == 0);
|
||||||
.buffer = buffer->buffer,
|
|
||||||
.offset = 0,
|
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
||||||
.range = VK_WHOLE_SIZE
|
VkDescriptorBufferInfo bufferInfo{
|
||||||
};
|
.buffer = buffer->gpuBuffers[i].buffer,
|
||||||
VkWriteDescriptorSet descriptorWrite{
|
.offset = offset,
|
||||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
.range = range
|
||||||
.pNext = nullptr,
|
};
|
||||||
.dstSet = set->set,
|
VkWriteDescriptorSet descriptorWrite{
|
||||||
.dstBinding = binding,
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
.dstArrayElement = 0,
|
.pNext = nullptr,
|
||||||
.descriptorCount = 1,
|
.dstSet = set->sets[i],
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
.dstBinding = binding,
|
||||||
.pImageInfo = nullptr,
|
.dstArrayElement = 0,
|
||||||
.pBufferInfo = &bufferInfo,
|
.descriptorCount = 1,
|
||||||
.pTexelBufferView = nullptr
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
};
|
.pImageInfo = nullptr,
|
||||||
vkUpdateDescriptorSets(pimpl->device.device, 1, &descriptorWrite, 0, nullptr);
|
.pBufferInfo = &bufferInfo,
|
||||||
|
.pTexelBufferView = nullptr
|
||||||
|
};
|
||||||
|
vkUpdateDescriptorSets(pimpl->device.device, 1, &descriptorWrite, 0, nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::updateUniformBuffer(const gfx::Pipeline* pipeline, const void* data, size_t size, uint32_t offset)
|
gfx::DescriptorBuffer* GFXDevice::createDescriptorBuffer(uint64_t size, const void* initialData)
|
||||||
{
|
{
|
||||||
|
gfx::DescriptorBuffer* out = new gfx::DescriptorBuffer{};
|
||||||
|
|
||||||
|
/* first make staging buffer */
|
||||||
|
out->stagingBuffer.size = size;
|
||||||
|
out->stagingBuffer.type = gfx::BufferType::UNIFORM;
|
||||||
|
out->stagingBuffer.hostVisible = true;
|
||||||
|
{
|
||||||
|
VkBufferCreateInfo stagingBufferInfo{};
|
||||||
|
stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
stagingBufferInfo.size = out->stagingBuffer.size;
|
||||||
|
stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||||
|
stagingBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
stagingBufferInfo.flags = 0;
|
||||||
|
|
||||||
#if 0
|
VmaAllocationCreateInfo stagingAllocInfo{};
|
||||||
assert(size <= pipeline->uniformBuffers[0]->size);
|
stagingAllocInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
||||||
|
stagingAllocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
|
||||||
|
stagingAllocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
||||||
|
|
||||||
[[maybe_unused]] VkResult res;
|
VKCHECK(vmaCreateBuffer(pimpl->allocator, &stagingBufferInfo, &stagingAllocInfo, &out->stagingBuffer.buffer, &out->stagingBuffer.allocation, nullptr));
|
||||||
|
|
||||||
for (gfx::Buffer* buffer : pipeline->uniformBuffers) {
|
void* dataDest;
|
||||||
void* uniformDest = nullptr;
|
VKCHECK(vmaMapMemory(pimpl->allocator, out->stagingBuffer.allocation, &dataDest));
|
||||||
res = vmaMapMemory(pimpl->allocator, buffer->allocation, &uniformDest);
|
memcpy(dataDest, initialData, out->stagingBuffer.size);
|
||||||
assert(res == VK_SUCCESS);
|
vmaUnmapMemory(pimpl->allocator, out->stagingBuffer.allocation);
|
||||||
memcpy((uint8_t*)uniformDest + offset, data, size);
|
}
|
||||||
vmaUnmapMemory(pimpl->allocator, buffer->allocation);
|
|
||||||
|
/* create the device-local set of buffers */
|
||||||
|
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
||||||
|
|
||||||
|
out->gpuBuffers[i].size = out->stagingBuffer.size;
|
||||||
|
out->gpuBuffers[i].type = gfx::BufferType::UNIFORM;
|
||||||
|
out->gpuBuffers[i].hostVisible = false;
|
||||||
|
|
||||||
|
VkBufferCreateInfo gpuBufferInfo{};
|
||||||
|
gpuBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
gpuBufferInfo.size = out->gpuBuffers[i].size;
|
||||||
|
gpuBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||||
|
gpuBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
gpuBufferInfo.flags = 0;
|
||||||
|
|
||||||
|
VmaAllocationCreateInfo gpuAllocationInfo{};
|
||||||
|
gpuAllocationInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
|
||||||
|
gpuAllocationInfo.flags = 0;
|
||||||
|
|
||||||
|
VKCHECK(vmaCreateBuffer(pimpl->allocator, &gpuBufferInfo, &gpuAllocationInfo, &out->gpuBuffers[i].buffer, &out->gpuBuffers[i].allocation, nullptr));
|
||||||
|
|
||||||
|
/* copy staging buffer into both */
|
||||||
|
copyBuffer(pimpl->device.device, pimpl->device.commandPools.transfer, pimpl->device.queues.transferQueues[0], out->stagingBuffer.buffer, out->gpuBuffers[i].buffer, out->stagingBuffer.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXDevice::destroyDescriptorBuffer(const gfx::DescriptorBuffer* descriptorBuffer)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
||||||
|
vmaDestroyBuffer(pimpl->allocator, descriptorBuffer->gpuBuffers[i].buffer, descriptorBuffer->gpuBuffers[i].allocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
vmaDestroyBuffer(pimpl->allocator, descriptorBuffer->stagingBuffer.buffer, descriptorBuffer->stagingBuffer.allocation);
|
||||||
|
|
||||||
|
delete descriptorBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXDevice::writeDescriptorBuffer(gfx::DescriptorBuffer* buffer, uint64_t offset, uint64_t size, const void* data)
|
||||||
|
{
|
||||||
|
assert(offset + size <= buffer->stagingBuffer.size);
|
||||||
|
|
||||||
|
/* first update the staging buffer */
|
||||||
|
void* dataDest;
|
||||||
|
VKCHECK(vmaMapMemory(pimpl->allocator, buffer->stagingBuffer.allocation, &dataDest));
|
||||||
|
memcpy(dataDest, (uint8_t*)data + offset, size);
|
||||||
|
vmaUnmapMemory(pimpl->allocator, buffer->stagingBuffer.allocation);
|
||||||
|
|
||||||
|
/* queue the writes to each gpu buffer */
|
||||||
|
// This is required as buffers cannot be updated if they are currently in use
|
||||||
|
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
||||||
|
pimpl->descriptorBufferWriteQueues[i].insert(buffer);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1178,8 +1273,8 @@ namespace engine {
|
|||||||
|
|
||||||
auto out = new gfx::Buffer{};
|
auto out = new gfx::Buffer{};
|
||||||
out->size = size;
|
out->size = size;
|
||||||
|
|
||||||
out->type = type;
|
out->type = type;
|
||||||
|
out->hostVisible = false;
|
||||||
|
|
||||||
VkBuffer stagingBuffer;
|
VkBuffer stagingBuffer;
|
||||||
VmaAllocation stagingAllocation;
|
VmaAllocation stagingAllocation;
|
||||||
@ -1457,6 +1552,11 @@ namespace engine {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t GFXDevice::getFrameCount()
|
||||||
|
{
|
||||||
|
return pimpl->FRAMECOUNT;
|
||||||
|
}
|
||||||
|
|
||||||
void GFXDevice::waitIdle()
|
void GFXDevice::waitIdle()
|
||||||
{
|
{
|
||||||
vkDeviceWaitIdle(pimpl->device.device);
|
vkDeviceWaitIdle(pimpl->device.device);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "resources/shader.hpp"
|
#include "resources/shader.hpp"
|
||||||
|
|
||||||
|
#include "application.hpp"
|
||||||
#include "gfx_device.hpp"
|
#include "gfx_device.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
|
|
||||||
@ -8,12 +9,10 @@
|
|||||||
namespace engine::resources {
|
namespace engine::resources {
|
||||||
|
|
||||||
|
|
||||||
Shader::Shader(GFXDevice* gfx, const char* vertPath, const char* fragPath, const VertexParams& vertexParams, bool alphaBlending, bool cullBackFace)
|
Shader::Shader(RenderData* renderData, const char* vertPath, const char* fragPath, const VertexParams& vertexParams, bool alphaBlending, bool cullBackFace)
|
||||||
: m_gfx(gfx)
|
: m_gfx(renderData->gfxdev.get())
|
||||||
{
|
{
|
||||||
|
|
||||||
m_setZeroLayout = m_gfx->createDescriptorSetLayout();
|
|
||||||
|
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
uint32_t stride = 0;
|
uint32_t stride = 0;
|
||||||
gfx::VertexFormat vertFormat{};
|
gfx::VertexFormat vertFormat{};
|
||||||
@ -45,26 +44,17 @@ namespace engine::resources {
|
|||||||
info.vertexFormat = vertFormat;
|
info.vertexFormat = vertFormat;
|
||||||
info.alphaBlending = alphaBlending;
|
info.alphaBlending = alphaBlending;
|
||||||
info.backfaceCulling = cullBackFace;
|
info.backfaceCulling = cullBackFace;
|
||||||
info.descriptorSetLayouts.push_back(m_setZeroLayout);
|
info.descriptorSetLayouts.push_back(renderData->setZeroLayout);
|
||||||
|
|
||||||
m_pipeline = m_gfx->createPipeline(info);
|
m_pipeline = m_gfx->createPipeline(info);
|
||||||
|
|
||||||
LOG_INFO("Loaded shader: {}, vertex attribs: {}", vertPath, vertFormat.attributeDescriptions.size());
|
LOG_INFO("Loaded shader: {}, vertex attribs: {}", vertPath, vertFormat.attributeDescriptions.size());
|
||||||
|
|
||||||
/* allocate uniform descriptor set */
|
|
||||||
m_setZero = m_gfx->allocateDescriptorSet(m_setZeroLayout);
|
|
||||||
/* fill with data */
|
|
||||||
glm::vec4 myValue = { 0.5f, 0.5f, 0.5f, 1.0f };
|
|
||||||
m_setZeroBuffer = m_gfx->createBuffer(gfx::BufferType::UNIFORM, sizeof(glm::vec4), &myValue);
|
|
||||||
m_gfx->updateDescriptor(m_setZero, 0, m_setZeroBuffer);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader::~Shader()
|
Shader::~Shader()
|
||||||
{
|
{
|
||||||
m_gfx->destroyBuffer(m_setZeroBuffer);
|
|
||||||
m_gfx->destroyPipeline(m_pipeline);
|
m_gfx->destroyPipeline(m_pipeline);
|
||||||
m_gfx->destroyDescriptorSetLayout(m_setZeroLayout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const gfx::Pipeline* Shader::getPipeline()
|
const gfx::Pipeline* Shader::getPipeline()
|
||||||
|
@ -15,20 +15,22 @@
|
|||||||
namespace engine {
|
namespace engine {
|
||||||
|
|
||||||
RenderSystem::RenderSystem(Scene* scene)
|
RenderSystem::RenderSystem(Scene* scene)
|
||||||
: System(scene, { typeid(TransformComponent).hash_code(), typeid(RenderableComponent).hash_code() })
|
: System(scene, { typeid(TransformComponent).hash_code(), typeid(RenderableComponent).hash_code() }),
|
||||||
|
m_gfx(m_scene->app()->gfx())
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderSystem::~RenderSystem()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderSystem::onUpdate(float ts)
|
void RenderSystem::onUpdate(float ts)
|
||||||
{
|
{
|
||||||
(void)ts;
|
(void)ts;
|
||||||
|
|
||||||
GFXDevice* const gfx = m_scene->app()->gfx();
|
|
||||||
|
|
||||||
gfx::DrawBuffer* drawBuffer = m_scene->app()->getDrawBuffer();
|
RenderData& renderData = m_scene->app()->renderData;
|
||||||
|
|
||||||
/* camera stuff */
|
/* camera stuff */
|
||||||
|
|
||||||
const auto cameraTransform = m_scene->getComponent<TransformComponent>(m_camera.camEntity);
|
const auto cameraTransform = m_scene->getComponent<TransformComponent>(m_camera.camEntity);
|
||||||
|
|
||||||
// do not render if camera is not set
|
// do not render if camera is not set
|
||||||
@ -38,14 +40,20 @@ namespace engine {
|
|||||||
|
|
||||||
if (m_scene->app()->window()->getWindowResized()) {
|
if (m_scene->app()->window()->getWindowResized()) {
|
||||||
uint32_t w, h;
|
uint32_t w, h;
|
||||||
gfx->getViewportSize(&w, &h);
|
m_gfx->getViewportSize(&w, &h);
|
||||||
m_viewportAspectRatio = (float)w / (float)h;
|
m_viewportAspectRatio = (float)w / (float)h;
|
||||||
}
|
}
|
||||||
const float verticalFovRadians = glm::radians(m_camera.verticalFovDegrees);
|
const float verticalFovRadians = glm::radians(m_camera.verticalFovDegrees);
|
||||||
// const float horizontalFovRadians = glm::radians(m_camera.horizontalFovDegrees);
|
|
||||||
// const float verticalFov = glm::atan( glm::tan(horizontalFovRadians / 2.0f) / m_viewportAspectRatio ) * 2.0f;
|
|
||||||
const glm::mat4 projMatrix = glm::perspectiveZO(verticalFovRadians, m_viewportAspectRatio, m_camera.clipNear, m_camera.clipFar);
|
const glm::mat4 projMatrix = glm::perspectiveZO(verticalFovRadians, m_viewportAspectRatio, m_camera.clipNear, m_camera.clipFar);
|
||||||
|
|
||||||
|
/* update SET 0 */
|
||||||
|
RenderData::SetZeroBuffer uniform{};
|
||||||
|
uniform.proj = projMatrix;
|
||||||
|
uniform.myValue.x = 1.0f;
|
||||||
|
m_value = glm::mod(m_value + ts, 1.0f);
|
||||||
|
uniform.myValue.y = m_value;
|
||||||
|
m_gfx->writeDescriptorBuffer(renderData.setZeroBuffer, 0, sizeof(RenderData::SetZeroBuffer), &uniform);
|
||||||
|
|
||||||
/* render all renderable entities */
|
/* render all renderable entities */
|
||||||
|
|
||||||
for (uint32_t entity : m_entities) {
|
for (uint32_t entity : m_entities) {
|
||||||
@ -59,16 +67,6 @@ namespace engine {
|
|||||||
assert(r->mesh != nullptr);
|
assert(r->mesh != nullptr);
|
||||||
//assert(r->material->m_texture != nullptr);
|
//assert(r->material->m_texture != nullptr);
|
||||||
|
|
||||||
struct {
|
|
||||||
glm::mat4 proj;
|
|
||||||
glm::mat4 view;
|
|
||||||
} uniform{};
|
|
||||||
|
|
||||||
uniform.proj = projMatrix;
|
|
||||||
uniform.view = viewMatrix;
|
|
||||||
|
|
||||||
gfx->updateUniformBuffer(r->material->getShader()->getPipeline(), &uniform, sizeof(glm::mat4) * 2, 0);
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
glm::mat4 model;
|
glm::mat4 model;
|
||||||
glm::mat4 view;
|
glm::mat4 view;
|
||||||
@ -77,21 +75,12 @@ namespace engine {
|
|||||||
pushConsts.model = t->worldMatrix;
|
pushConsts.model = t->worldMatrix;
|
||||||
pushConsts.view = viewMatrix;
|
pushConsts.view = viewMatrix;
|
||||||
|
|
||||||
gfx->cmdBindPipeline(drawBuffer, r->material->getShader()->getPipeline());
|
m_gfx->cmdBindPipeline(renderData.drawBuffer, r->material->getShader()->getPipeline());
|
||||||
gfx->cmdBindDescriptorSet(drawBuffer, r->material->getShader()->getPipeline(), r->material->getShader()->getSetZero(), 0);
|
m_gfx->cmdBindDescriptorSet(renderData.drawBuffer, r->material->getShader()->getPipeline(), renderData.setZero, 0);
|
||||||
gfx->cmdBindVertexBuffer(drawBuffer, 0, r->mesh->getVB());
|
m_gfx->cmdPushConstants(renderData.drawBuffer, r->material->getShader()->getPipeline(), 0, sizeof(pushConsts), &pushConsts);
|
||||||
gfx->cmdBindIndexBuffer(drawBuffer, r->mesh->getIB());
|
m_gfx->cmdBindVertexBuffer(renderData.drawBuffer, 0, r->mesh->getVB());
|
||||||
gfx->cmdDrawIndexed(drawBuffer, r->mesh->getCount(), 1, 0, 0, 0);
|
m_gfx->cmdBindIndexBuffer(renderData.drawBuffer, r->mesh->getIB());
|
||||||
|
m_gfx->cmdDrawIndexed(renderData.drawBuffer, r->mesh->getCount(), 1, 0, 0, 0);
|
||||||
/*
|
|
||||||
gfx->draw(
|
|
||||||
r->material->getShader()->getPipeline(),
|
|
||||||
r->mesh->getVB(),
|
|
||||||
r->mesh->getIB(),
|
|
||||||
r->mesh->getCount(),
|
|
||||||
&pushConsts,
|
|
||||||
sizeof(pushConsts)
|
|
||||||
);*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include <SDL2/SDL_vulkan.h>
|
#include <SDL2/SDL_vulkan.h>
|
||||||
|
|
||||||
|
#include "log.hpp"
|
||||||
|
|
||||||
#include "swapchain.h"
|
#include "swapchain.h"
|
||||||
|
|
||||||
namespace engine {
|
namespace engine {
|
||||||
@ -13,7 +15,7 @@ namespace engine {
|
|||||||
{
|
{
|
||||||
sc->device = info.device;
|
sc->device = info.device;
|
||||||
|
|
||||||
printf("Recreating swapchain!\n");
|
LOG_INFO("Recreating swapchain!\n");
|
||||||
|
|
||||||
// get surface caps and features
|
// get surface caps and features
|
||||||
VkResult res;
|
VkResult res;
|
||||||
|
@ -57,32 +57,6 @@ void playGame(bool enableFrameLimiter)
|
|||||||
|
|
||||||
auto myScene = app.sceneManager()->createEmptyScene();
|
auto myScene = app.sceneManager()->createEmptyScene();
|
||||||
|
|
||||||
const std::string vertPath = app.getResourcePath("engine/shaders/test.vert");
|
|
||||||
const std::string fragPath = app.getResourcePath("engine/shaders/test.frag");
|
|
||||||
engine::resources::Shader::VertexParams vertexParams{};
|
|
||||||
vertexParams.hasColor = false;
|
|
||||||
vertexParams.hasNormal = true;
|
|
||||||
vertexParams.hasTangent = false;
|
|
||||||
vertexParams.hasUV0 = true;
|
|
||||||
bool alphaBlending = false;
|
|
||||||
bool cullBackFace = true;
|
|
||||||
auto testShader = std::make_shared<engine::resources::Shader>(app.gfx(), vertPath.c_str(), fragPath.c_str(), vertexParams, alphaBlending, cullBackFace);
|
|
||||||
|
|
||||||
auto camera = myScene->createEntity("camera");
|
|
||||||
|
|
||||||
auto renderSystem = myScene->getSystem<engine::RenderSystem>();
|
|
||||||
renderSystem->setCameraEntity(camera);
|
|
||||||
myScene->getComponent<engine::TransformComponent>(camera)->position = { 0.0f, 10.0f, 0.0f };
|
|
||||||
|
|
||||||
/* cube */
|
|
||||||
uint32_t cube = myScene->createEntity("cube");
|
|
||||||
myScene->getComponent<engine::TransformComponent>(cube)->position = glm::vec3{ -0.5f, -0.5f, -0.5f };
|
|
||||||
auto cubeRenderable = myScene->addComponent<engine::RenderableComponent>(cube);
|
|
||||||
cubeRenderable->material = std::make_shared<engine::resources::Material>(testShader);
|
|
||||||
cubeRenderable->mesh = genCuboidMesh(app.gfx(), 1, 1.0f, 1, 1);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
/* create camera */
|
/* create camera */
|
||||||
{
|
{
|
||||||
myScene->registerComponent<CameraControllerComponent>();
|
myScene->registerComponent<CameraControllerComponent>();
|
||||||
@ -130,6 +104,15 @@ void playGame(bool enableFrameLimiter)
|
|||||||
myScene->getComponent<engine::TransformComponent>(skybox)->position = { -1.0f, -1.0f, -1.0f };
|
myScene->getComponent<engine::TransformComponent>(skybox)->position = { -1.0f, -1.0f, -1.0f };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* cube */
|
||||||
|
{
|
||||||
|
uint32_t cube = myScene->createEntity("cube");
|
||||||
|
myScene->getComponent<engine::TransformComponent>(cube)->position = glm::vec3{ -0.5f, -0.5f, -0.5f };
|
||||||
|
auto cubeRenderable = myScene->addComponent<engine::RenderableComponent>(cube);
|
||||||
|
cubeRenderable->material = std::make_shared<engine::resources::Material>(app.getResource<engine::resources::Shader>("builtin.standard"));
|
||||||
|
cubeRenderable->mesh = genCuboidMesh(app.gfx(), 1.0f, 1.0f, 1.0f, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* floor */
|
/* floor */
|
||||||
{
|
{
|
||||||
uint32_t floor = myScene->createEntity("floor");
|
uint32_t floor = myScene->createEntity("floor");
|
||||||
@ -138,13 +121,12 @@ void playGame(bool enableFrameLimiter)
|
|||||||
floorRenderable->material = std::make_shared<engine::resources::Material>(app.getResource<engine::resources::Shader>("builtin.standard"));
|
floorRenderable->material = std::make_shared<engine::resources::Material>(app.getResource<engine::resources::Shader>("builtin.standard"));
|
||||||
floorRenderable->material->m_texture = grassTexture;
|
floorRenderable->material->m_texture = grassTexture;
|
||||||
floorRenderable->mesh = genCuboidMesh(app.gfx(), 10000.0f, 1.0f, 10000.0f, 5000.0f);
|
floorRenderable->mesh = genCuboidMesh(app.gfx(), 10000.0f, 1.0f, 10000.0f, 5000.0f);
|
||||||
|
floorRenderable->shown = true;
|
||||||
auto floorCollider = myScene->addComponent<engine::ColliderComponent>(floor);
|
auto floorCollider = myScene->addComponent<engine::ColliderComponent>(floor);
|
||||||
floorCollider->isStatic = true;
|
floorCollider->isStatic = true;
|
||||||
floorCollider->aabb = { { 0.0f, 0.0f, 0.0f }, { 10000.0f, 1.0f, 10000.0f } };
|
floorCollider->aabb = { { 0.0f, 0.0f, 0.0f }, { 10000.0f, 1.0f, 10000.0f } };
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
app.gameLoop();
|
app.gameLoop();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user