diff --git a/sandbox/main.cpp b/sandbox/main.cpp index bd62059..5672ff7 100644 --- a/sandbox/main.cpp +++ b/sandbox/main.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -12,13 +13,24 @@ #include "renderer/render_graph.hpp" #include "renderer/scene_renderer.hpp" #include "resources/resource_registry.hpp" +#include "vulkan/buffer.hpp" #include "vulkan/device.hpp" +#include "vulkan/shader.hpp" #include "window.hpp" constexpr uint32_t WIDTH = 1280; constexpr uint32_t HEIGHT = 720; constexpr const char* NAME = "sandbox"; +void immediate_submit(sophia::Device& device, + std::function&& function) { + auto command = device.beginSingleTimeCommands(); + function(command); + device.endSingleTimeCommands(command); +} + +#include "material.hpp" + int main() { sophia::Window window{WIDTH, HEIGHT, NAME}; sophia::Device device{&window}; @@ -30,10 +42,55 @@ int main() { sophia::SceneRenderer sceneRenderer{sceneRegistry, resourceRegistry, device, renderContext.getImageFormat()}; + sophia::SceneHandle sceneHandle = sceneRegistry.create(); + sophia::Scene& scene = sceneRegistry.get(sceneHandle); + sophia::Entity camera = scene.createCamera(); + + // { + // auto& transform = camera.getComponent(); + // transform.position.z += 60; + // } + sophia::SceneView view; - view.scene = sceneRegistry.create(); + view.scene = sceneHandle; view.clearColor = {0.01f, 0.01f, 0.02f, 1.0f}; - view.camera = sceneRegistry.get(view.scene).createCamera(); + view.camera = camera; + + auto vertexShader = sophia::Shader::Builder() + .fromGLSL(SANDBOX_SHADER_DIR "/triangle.vert") + .setStage(sophia::ShaderStage::VERTEX) + .build(); + auto fragmentShader = sophia::Shader::Builder() + .fromGLSL(SANDBOX_SHADER_DIR "/triangle.frag") + .setStage(sophia::ShaderStage::FRAGMENT) + .build(); + vk::Format depthFormat = resourceRegistry.renderTargetPool.getDepthFormat(); + sophia::Material material{device, std::move(vertexShader), + std::move(fragmentShader), + renderContext.getImageFormat(), depthFormat}; + + struct TriangleVertex { + sophia::vec4 vertex; + sophia::vec4 color; + }; + + TriangleVertex verticies[] = { + {{-1.f, 1.f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 0.0f}}, + {{1.f, 1.f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}}, + {{0.f, -1.f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}}}; + sophia::u32 triangleVerticiesCount = 3; + + sophia::Buffer triangleBuffer{device, sizeof(TriangleVertex), + triangleVerticiesCount, + vk::BufferUsageFlagBits::eShaderDeviceAddress, + vk::MemoryPropertyFlagBits::eHostVisible | + vk::MemoryPropertyFlagBits::eHostCoherent}; + triangleBuffer.map(); + + triangleBuffer.writeToBuffer(verticies); + + vk::DeviceAddress address = + device.get()->getBufferAddress({triangleBuffer.getBuffer()}); while (!window.shouldClose()) { glfwPollEvents(); @@ -52,7 +109,7 @@ int main() { renderContext.getCurrentDepthImage(), sophia::Access::DepthWrite); graph.addPass( - "scene", + "sandbox", [&](sophia::RenderGraph::PassBuilder& pass) { const sophia::vec4& c = view.clearColor; pass.writeColor(color, vk::AttachmentLoadOp::eClear, @@ -60,11 +117,33 @@ int main() { pass.writeDepth(depth, vk::AttachmentLoadOp::eClear); }, [&](vk::CommandBuffer commandBuffer) { - ZoneScopedN("scene pass"); - sceneRenderer.render(commandBuffer, view, view.camera, - renderContext.getExtent()); + ZoneScopedN("main sandbox pass"); + material.bind(commandBuffer); + sophia::Material::PushConstants push; + push.data0 = address; + + commandBuffer.pushConstants( + material.getLayout(), vk::ShaderStageFlagBits::eVertex, 0, + sizeof(sophia::Material::PushConstants), &push); + commandBuffer.draw(3, 1, 0, 0); }); + /* + graph.addPass( + "scene", + [&](sophia::RenderGraph::PassBuilder& pass) { + const sophia::vec4& c = view.clearColor; + pass.writeColor(color, vk::AttachmentLoadOp::eClear, + {c.r, c.g, c.b, c.a}); + pass.writeDepth(depth, vk::AttachmentLoadOp::eClear); + }, + [&](vk::CommandBuffer commandBuffer) { + ZoneScopedN("scene pass"); + sceneRenderer.render(commandBuffer, view, view.camera, + renderContext.getExtent()); + }); + */ + graph.execute(commandBuffer); renderContext.endFrame(); diff --git a/sandbox/material.cpp b/sandbox/material.cpp new file mode 100644 index 0000000..b79baef --- /dev/null +++ b/sandbox/material.cpp @@ -0,0 +1,45 @@ +#include "material.hpp" + +#include + +namespace sophia { + +Material::Material(Device& device, std::unique_ptr vertexShader, + std::unique_ptr fragmentShader, + vk::Format colorFormat, vk::Format depthFormat) { + createPipelineLayout(device); + this->pipeline = GraphicsPipeline::Builder(device) + .setVertexShader(*vertexShader) + .setFragmentShader(*fragmentShader) + .setPipelineLayout(this->pipelineLayout.get()) + .setColorAttachmentFormats({colorFormat}) + .setDepthAttachmentFormat(depthFormat) + .setDepthTest(true, true) + .setCullMode(vk::CullModeFlagBits::eBack) + .build(); +} + +Material::~Material() { log::trace("destroyed sophia::Material"); } + +void Material::createPipelineLayout(Device& device) { + vk::PushConstantRange pushConstantRange{}; + pushConstantRange.stageFlags = vk::ShaderStageFlagBits::eVertex; + pushConstantRange.offset = 0; + pushConstantRange.size = sizeof(PushConstants); + + vk::PipelineLayoutCreateInfo pipelineLayoutInfo = {}; + pipelineLayoutInfo.setLayoutCount = 0; + pipelineLayoutInfo.pushConstantRangeCount = 1; + pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; + + try { + this->pipelineLayout = + device.get()->createPipelineLayoutUnique(pipelineLayoutInfo); + log::trace("created vk::PipelineLayout"); + } catch (const vk::SystemError& err) { + log::fatal("failed to create vk::PipelineLayout"); + throw std::runtime_error("failed to create vk::PipelineLayout"); + } +} + +} // namespace sophia diff --git a/sandbox/material.hpp b/sandbox/material.hpp new file mode 100644 index 0000000..1fd51a5 --- /dev/null +++ b/sandbox/material.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include + +#include "vulkan/device.hpp" +#include "vulkan/pipelines/graphics_pipeline.hpp" +#include "vulkan/shader.hpp" + +namespace sophia { + +class Material { + public: + struct PushConstants { + vk::DeviceAddress data0; + u64 padding; + vec4 data1; + vec4 data2; + vec4 data3; + }; + + Material(const Material&) = delete; + Material& operator=(const Material&) = delete; + + Material(Device& device, std::unique_ptr vertexShader, + std::unique_ptr fragmentShader, vk::Format colorFormat, + vk::Format depthFormat); + ~Material(); + + void bind(vk::CommandBuffer commandBuffer) const { + pipeline->bind(commandBuffer); + } + vk::PipelineLayout getLayout() const { return pipelineLayout.get(); } + + private: + void createPipelineLayout(Device& device); + + vk::UniquePipelineLayout pipelineLayout; + std::unique_ptr pipeline; +}; + +struct MaterialInstance { + Material* material; +}; + +// !NOTE: eventually add ecs support for ecs +// struct MaterialComponent { +// MaterialInstanceHandle handle; +// }; + +} // namespace sophia diff --git a/sandbox/renderer.cpp b/sandbox/renderer.cpp new file mode 100644 index 0000000..1d75a4c --- /dev/null +++ b/sandbox/renderer.cpp @@ -0,0 +1,3 @@ +#include "renderer.hpp" + +namespace sophia {} // namespace sophia diff --git a/sandbox/renderer.hpp b/sandbox/renderer.hpp new file mode 100644 index 0000000..0d50fff --- /dev/null +++ b/sandbox/renderer.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +#include "material.hpp" + +namespace sophia { + +struct RenderObject { + uint32_t indexCount; + uint32_t firstIndex; + vk::Buffer indexBuffer; + + MaterialInstance* material; + + mat4 transform; + VkDeviceAddress vertexBufferAddress; +}; + +class Renderer { + public: + private: +}; + +} // namespace sophia diff --git a/sandbox/shaders/triangle.frag b/sandbox/shaders/triangle.frag new file mode 100644 index 0000000..d67c317 --- /dev/null +++ b/sandbox/shaders/triangle.frag @@ -0,0 +1,13 @@ +#version 450 + +//shader input +layout (location = 0) in vec3 inColor; + +//output write +layout (location = 0) out vec4 outFragColor; + +void main() +{ + //return red + outFragColor = vec4(inColor,1.0f); +} diff --git a/sandbox/shaders/triangle.vert b/sandbox/shaders/triangle.vert new file mode 100644 index 0000000..1873496 --- /dev/null +++ b/sandbox/shaders/triangle.vert @@ -0,0 +1,45 @@ +#version 450 +#extension GL_EXT_buffer_reference : require + +struct TriangleVertex { + vec4 vertex; + vec4 color; +}; + +layout(buffer_reference, std430) readonly buffer TriangleVertexBuffer { + TriangleVertex vertices[]; +}; + +layout( push_constant ) uniform constants { + TriangleVertexBuffer triangleBuffer; + vec2 padding; + vec4 data1; + vec4 data2; + vec4 data3; +} PushConstants; + +layout (location = 0) out vec3 outColor; + +void main() +{ + //const array of positions for the triangle + const vec3 positions[3] = vec3[3]( + vec3(-1.f,1.f, 0.0f), + vec3(1.f,1.f, 0.0f), + vec3(0.f,-1.f, 0.0f) + ); + + //const array of colors for the triangle + const vec3 colors[3] = vec3[3]( + vec3(1.0f, 0.0f, 0.0f), //red + vec3(0.0f, 1.0f, 0.0f), //green + vec3(00.f, 0.0f, 1.0f) //blue + ); + + // Load vertex data from device address + TriangleVertex v = PushConstants.triangleBuffer.vertices[gl_VertexIndex]; + + // output the position of each vertex + gl_Position = vec4(v.vertex.xyz, 1.0); + outColor = vec3(v.color.xyz); +} diff --git a/sandbox/shaders/vkguide_gradient.comp b/sandbox/shaders/vkguide_gradient.comp new file mode 100644 index 0000000..084ab83 --- /dev/null +++ b/sandbox/shaders/vkguide_gradient.comp @@ -0,0 +1,27 @@ +#version 460 + +//size of a workgroup for compute +layout (local_size_x = 16, local_size_y = 16) in; + +//descriptor bindings for the pipeline +layout(rgba16f,set = 0, binding = 0) uniform image2D image; + + +void main() +{ + ivec2 texelCoord = ivec2(gl_GlobalInvocationID.xy); + ivec2 size = imageSize(image); + + if(texelCoord.x < size.x && texelCoord.y < size.y) + { + vec4 color = vec4(0.0, 0.0, 0.0, 1.0); + + if(gl_LocalInvocationID.x != 0 && gl_LocalInvocationID.y != 0) + { + color.x = float(texelCoord.x)/(size.x); + color.y = float(texelCoord.y)/(size.y); + } + + imageStore(image, texelCoord, color); + } +}