diff --git a/.idea/editor.xml b/.idea/editor.xml
index 8d0e15e..33921db 100644
--- a/.idea/editor.xml
+++ b/.idea/editor.xml
@@ -246,100 +246,22 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index c5c142a..94a25f7 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,7 +2,5 @@
-
-
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dd73e75..fbff8b8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,6 +8,20 @@ include(FetchContent)
variable_watch($ENV{VULKAN_SDK})
find_package(Vulkan REQUIRED COMPONENTS volk)
+find_library(SLANG_LIB NAMES slang HINTS "$ENV{VULKAN_SDK}/lib")
+find_path(SLANG_INCLUDE_DIR NAMES slang/slang.h HINTS "$ENV{VULKAN_SDK}/include")
+
+if(SLANG_LIB AND SLANG_INCLUDE_DIR)
+ add_library(slang_sdk SHARED IMPORTED)
+ set_target_properties(slang_sdk PROPERTIES
+ IMPORTED_LOCATION "${SLANG_LIB}"
+ INTERFACE_INCLUDE_DIRECTORIES "${SLANG_INCLUDE_DIR}"
+ )
+ message(STATUS "Slang found via VULKAN_SDK: ${SLANG_LIB}")
+else()
+ message(FATAL_ERROR "VULKAN_SDK env var is set, but Slang wasn't found inside it!")
+endif()
+
FetchContent_Declare(
glfw
GIT_REPOSITORY https://github.com/glfw/glfw.git
@@ -27,6 +41,7 @@ FetchContent_Declare(
GIT_REPOSITORY https://github.com/nothings/stb.git
GIT_TAG master
)
+
FetchContent_MakeAvailable(stb)
add_library(stb INTERFACE)
@@ -51,7 +66,7 @@ target_include_directories(v
${CMAKE_CURRENT_SOURCE_DIR}
)
-target_link_libraries(v PRIVATE glfw Vulkan::Vulkan glm stb)
+target_link_libraries(v PRIVATE glfw Vulkan::Vulkan glm stb slang_sdk)
set(SHADER_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/shaders")
set(SHADER_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/shaders")
diff --git a/main.cpp b/main.cpp
index 09900f3..7098185 100644
--- a/main.cpp
+++ b/main.cpp
@@ -37,6 +37,8 @@ int main() {
createSwapchain(window);
+ slang::createGlobalSession(slangGlobalSession.writeRef());
+
Renderer renderer(window);
texture_manager.load("assets/boy.jpg", renderer);
@@ -47,7 +49,9 @@ int main() {
renderer.begin_frame();
- renderer.submit_quad();
+ renderer.submit_quad({-0.5, 0.0});
+
+ renderer.submit_quad({0.5, 0.0});
// renderer.submit_sprite();
diff --git a/renderer/init.cpp b/renderer/init.cpp
index ef06c75..6caa8e9 100644
--- a/renderer/init.cpp
+++ b/renderer/init.cpp
@@ -236,7 +236,7 @@ void createDevice() {
VkPhysicalDeviceVulkan13Features enabledVk13Features{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
- .pNext = nullptr,
+ .pNext = &enabledVk14Features,
.robustImageAccess = false,
.inlineUniformBlock = false,
.descriptorBindingInlineUniformBlockUpdateAfterBind = false,
@@ -264,13 +264,20 @@ void createDevice() {
.runtimeDescriptorArray = true,
.bufferDeviceAddress = true,
};
+
+ VkPhysicalDeviceVulkan11Features enabledVk11Features{
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
+ .pNext = &enabledVk12Features,
+ .shaderDrawParameters = true,
+ };
+
const VkPhysicalDeviceFeatures enabledVk10Features{
.samplerAnisotropy = true,
};
const VkDeviceCreateInfo dci{
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
- .pNext = &enabledVk12Features,
+ .pNext = &enabledVk11Features,
.queueCreateInfoCount = 1,
.pQueueCreateInfos = &qci,
.enabledExtensionCount = (uint32_t)devExts.size(),
diff --git a/renderer/renderer.cpp b/renderer/renderer.cpp
index 835989f..2a857f9 100644
--- a/renderer/renderer.cpp
+++ b/renderer/renderer.cpp
@@ -6,6 +6,7 @@
#include "init.h"
#include "sprite.h"
#include
+#include
bool SortKey::operator<(const SortKey& b) const {
if (depth != b.depth) return depth < b.depth;
@@ -16,7 +17,7 @@ bool SortKey::operator<(const SortKey& b) const {
Renderer::Renderer(GLFWwindow *window) {
create_pipeline_layout();
- colored_quad_pipeline = create_graphics_pipeline(
+ colored_quad_pipeline = create_graphics_pipeline(
device,
pipelineLayout,
swapchain_format.format,
@@ -36,8 +37,7 @@ void Renderer::flush() {
}
-void Renderer::submit_quad() {
- glm::vec2 pos = {0, 0};
+void Renderer::submit_quad(glm::vec2 pos) {
RenderCommand cmd {};
cmd.pipeline = PipelineType::ColoredQuad;
cmd.key = {
@@ -47,8 +47,8 @@ void Renderer::submit_quad() {
};
cmd.colored_quad = {
- .position = pos,
- .size = {0.25, 0.25},
+ .pos = pos,
+ .scale = {0.25, 0.25},
.color = {0, 1, 1, 1},
};
@@ -552,7 +552,7 @@ void Renderer::end_frame() {
return cmd.key.depth;
});
- std::vector vertices;
+ std::vector vertices;
for (auto& cmd : commands) {
@@ -562,10 +562,10 @@ void Renderer::end_frame() {
const auto &q = cmd.colored_quad;
// Calculate spatial corners
- float x0 = q.position.x;
- float y0 = q.position.y;
- float x1 = q.position.x + q.size.x;
- float y1 = q.position.y + q.size.y;
+ //float x0 = q.position.x;
+ //float y0 = q.position.y;
+ //float x1 = q.position.x + q.size.x;
+ //float y1 = q.position.y + q.size.y;
// Calculate UV corners
// float u0 = q.uvMin.x;
@@ -574,25 +574,23 @@ void Renderer::end_frame() {
// float v1 = q.uvMax.y;
// Define the 4 corners of the quad
- vertex_p2_st2_col4_a1_u32 vTL = { {x0, y0}, {0, 0}, q.color, 1, 0 };
- vertex_p2_st2_col4_a1_u32 vTR = { {x1, y0}, {0, 0}, q.color, 1, 0 };
- vertex_p2_st2_col4_a1_u32 vBL = { {x0, y1}, {0, 0}, q.color, 1, 0 };
- vertex_p2_st2_col4_a1_u32 vBR = { {x1, y1}, {0, 0}, q.color, 1, 0 };
+ vertex_p2_s2_st2_col4_a1_u32 vTL = { q.pos, q.scale, {0, 0}, q.color, 1, 0 };
+ vertex_p2_s2_st2_col4_a1_u32 vTR = { q.pos, q.scale, {0, 0}, q.color, 1, 0 };
+ vertex_p2_s2_st2_col4_a1_u32 vBL = { q.pos, q.scale, {0, 0}, q.color, 1, 0 };
+ vertex_p2_s2_st2_col4_a1_u32 vBR = { q.pos, q.scale, {0, 0}, q.color, 1, 0 };
// vertex_p2_st2_col4_a1_u32 vTL = { {x0, y0}, {u0, v0}, q.color, 1, q.textureID };
// vertex_p2_st2_col4_a1_u32 vTR = { {x1, y0}, {u1, v0}, q.color, 1, q.textureID };
// vertex_p2_st2_col4_a1_u32 vBL = { {x0, y1}, {u0, v1}, q.color, 1, q.textureID };
// vertex_p2_st2_col4_a1_u32 vBR = { {x1, y1}, {u1, v1}, q.color, 1, q.textureID };
- // --- Triangle 1 (TL, TR, BL) ---
vertices.push_back(vTL);
- vertices.push_back(vTR);
vertices.push_back(vBL);
+ vertices.push_back(vTR);
- // --- Triangle 2 (TR, BR, BL) ---
vertices.push_back(vTR);
- vertices.push_back(vBR);
vertices.push_back(vBL);
+ vertices.push_back(vBR);
break;
}
@@ -670,14 +668,15 @@ void Renderer::end_frame() {
void Renderer::upload_vertex_buffer(
VkCommandBuffer cmd,
const Frame &frame,
- std::span vertices) const {
+ std::span vertices) const
+{
VkMemoryPropertyFlags memPropFlags;
vmaGetAllocationMemoryProperties(allocator, frame.vertexBuffer.allocation, &memPropFlags);
if(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
// The Allocation ended up in a mappable memory.
// Calling vmaCopyMemoryToAllocation() does vmaMapMemory(), memcpy(), vmaUnmapMemory(), and vmaFlushAllocation().
- VkResult result = vmaCopyMemoryToAllocation(allocator, vertices.data(), frame.vertexBuffer.allocation, 0, vertices.size() * sizeof(vertex_p2_st2_col4_a1_u32));
+ VkResult result = vmaCopyMemoryToAllocation(allocator, vertices.data(), frame.vertexBuffer.allocation, 0, vertices.size() * sizeof(vertex_p2_s2_st2_col4_a1_u32));
// Check result...
VkBufferMemoryBarrier bufMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
@@ -702,7 +701,7 @@ void Renderer::recordCommandBuffer(
VkExtent2D extent,
VkImageLayout oldLayout,
const Frame &frame,
- const std::vector &vertices) const
+ const std::vector &vertices) const
{
{
diff --git a/renderer/renderer.h b/renderer/renderer.h
index 15bc2c3..cd2036d 100644
--- a/renderer/renderer.h
+++ b/renderer/renderer.h
@@ -15,6 +15,10 @@
#include
#include
#include
+#include
+#include
+
+inline Slang::ComPtr slangGlobalSession;
enum class PROJECTION_TYPE : uint8_t {
NONE,
@@ -25,25 +29,27 @@ enum class PROJECTION_TYPE : uint8_t {
COUNT,
};
-struct vertex_p2_st2_col4_a1_u32 {
+struct vertex_p2_s2_st2_col4_a1_u32 {
glm::vec2 pos;
- glm::vec2 st;
- glm::vec4 col;
+ glm::vec2 scale;
+ glm::vec2 uv;
+ glm::vec4 color;
float alpha;
uint32_t textureID;
static VkVertexInputBindingDescription getBindingDescription() {
- return {0, sizeof(vertex_p2_st2_col4_a1_u32), VK_VERTEX_INPUT_RATE_VERTEX};
+ return {0, sizeof(vertex_p2_s2_st2_col4_a1_u32), VK_VERTEX_INPUT_RATE_VERTEX};
}
- static std::array getAttributeDescriptions() {
+ static std::array getAttributeDescriptions() {
return {
{
- {0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(vertex_p2_st2_col4_a1_u32, pos)},
- {1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(vertex_p2_st2_col4_a1_u32, st)},
- {2, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(vertex_p2_st2_col4_a1_u32, col)},
- {3, 0, VK_FORMAT_R32_SFLOAT, offsetof(vertex_p2_st2_col4_a1_u32, alpha)},
- {4, 0, VK_FORMAT_R32_UINT, offsetof(vertex_p2_st2_col4_a1_u32, textureID)},
+ {0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(vertex_p2_s2_st2_col4_a1_u32, pos)},
+ {1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(vertex_p2_s2_st2_col4_a1_u32, scale)},
+ {2, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(vertex_p2_s2_st2_col4_a1_u32, uv)},
+ {3, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(vertex_p2_s2_st2_col4_a1_u32, color)},
+ {4, 0, VK_FORMAT_R32_SFLOAT, offsetof(vertex_p2_s2_st2_col4_a1_u32, alpha)},
+ {5, 0, VK_FORMAT_R32_UINT, offsetof(vertex_p2_s2_st2_col4_a1_u32, textureID)},
}
};
}
@@ -70,8 +76,8 @@ struct TexturedQuadCmd {
};
struct ColoredQuadCmd {
- glm::vec2 position;
- glm::vec2 size;
+ glm::vec2 pos;
+ glm::vec2 scale;
glm::vec4 color;
};
@@ -167,7 +173,7 @@ struct Renderer {
void flush();
void submit_sprite(glm::vec2 pos, const sprite_t &sprite);
- void submit_quad();
+ void submit_quad(glm::vec2 pos);
explicit Renderer(GLFWwindow *window);
void create_pipeline_layout();
@@ -180,7 +186,7 @@ struct Renderer {
VkExtent2D extent,
VkImageLayout oldLayout,
const Frame &frame,
- const std::vector &vertices) const;
+ const std::vector &vertices) const;
void immediate_submit(std::function&& func) const;
void transition_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout) const;
VkImageView create_image_view(VkImage image, VkFormat format) const;
@@ -190,7 +196,7 @@ struct Renderer {
void upload_vertex_buffer(
VkCommandBuffer cmd,
const Frame &frame,
- std::span vertices) const;
+ std::span vertices) const;
VkPipeline get_pipeline(PipelineType type) const;
// void bind_material(VkCommandBuffer cmd, uint16_t materialID);
@@ -211,6 +217,38 @@ struct Renderer {
bool enableBlending)
{
+ auto slangTargets{ std::to_array({ {
+ .format = SLANG_SPIRV,
+ .profile = slangGlobalSession->findProfile("spirv_1_4")
+ } })};
+ auto slangOptions{ std::to_array({ {
+ slang::CompilerOptionName::EmitSpirvDirectly,
+ {slang::CompilerOptionValueKind::Int, 1}
+ } })};
+ slang::SessionDesc slangSessionDesc{
+ .targets = slangTargets.data(),
+ .targetCount = SlangInt(slangTargets.size()),
+ .defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR,
+ .compilerOptionEntries = slangOptions.data(),
+ .compilerOptionEntryCount = uint32_t(slangOptions.size())
+ };
+ Slang::ComPtr slangSession;
+ slangGlobalSession->createSession(slangSessionDesc, slangSession.writeRef());
+
+ Slang::ComPtr slangModule{
+ slangSession->loadModuleFromSource("triangle", "shaders/shader.slang", nullptr, nullptr)
+ };
+ Slang::ComPtr spirv;
+ slangModule->getTargetCode(0, spirv.writeRef());
+
+ VkShaderModuleCreateInfo shaderModuleCI{
+ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ .codeSize = spirv->getBufferSize(),
+ .pCode = (uint32_t*)spirv->getBufferPointer()
+ };
+ VkShaderModule shaderModule{};
+ vkCreateShaderModule(device, &shaderModuleCI, nullptr, &shaderModule);
+
auto vsCode = loadFile("shaders/triangle.vert.spv");
auto fsCode = loadFile("shaders/triangle.frag.spv");
@@ -220,32 +258,22 @@ struct Renderer {
smci.codeSize = vsCode.size();
smci.pCode = reinterpret_cast(vsCode.data());
- VkShaderModule vs;
- vkCreateShaderModule(device, &smci, nullptr, &vs);
+ // VkShaderModule vs;
+ // vkCreateShaderModule(device, &smci, nullptr, &vs);
smci.codeSize = fsCode.size();
smci.pCode = reinterpret_cast(fsCode.data());
- VkShaderModule fs;
- vkCreateShaderModule(device, &smci, nullptr, &fs);
+ // VkShaderModule fs;
+ // vkCreateShaderModule(device, &smci, nullptr, &fs);
// --- Shaders ---
- VkPipelineShaderStageCreateInfo stages[2] = {
- {
- VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- nullptr,
- 0,
- VK_SHADER_STAGE_VERTEX_BIT,
- vs,
- "main"
- },
- {
- VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- nullptr,
- 0,
- VK_SHADER_STAGE_FRAGMENT_BIT,
- fs,
- "main"
- }
+ std::vector shaderStages{
+ { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .stage = VK_SHADER_STAGE_VERTEX_BIT,
+ .module = shaderModule, .pName = "main"},
+ { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
+ .module = shaderModule, .pName = "main" }
};
// --- Vertex Input (Generic) ---
@@ -296,7 +324,7 @@ struct Renderer {
0,
VK_POLYGON_MODE_FILL,
VK_CULL_MODE_NONE,
- VK_FRONT_FACE_CLOCKWISE,
+ VK_FRONT_FACE_COUNTER_CLOCKWISE,
0,
0,
0,
@@ -341,8 +369,8 @@ struct Renderer {
VkGraphicsPipelineCreateInfo gpci{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &rci,
- .stageCount = 2,
- .pStages = stages,
+ .stageCount = (uint32_t) shaderStages.size(),
+ .pStages = shaderStages.data(),
.pVertexInputState = &vi,
.pInputAssemblyState = &ia,
.pViewportState = &vp,
diff --git a/shaders/shader.slang b/shaders/shader.slang
new file mode 100644
index 0000000..6606636
--- /dev/null
+++ b/shaders/shader.slang
@@ -0,0 +1,48 @@
+struct VSInput {
+ float2 pos;
+ float2 scale;
+ float2 uv;
+ float4 color;
+ float alpha;
+ uint32_t textureID;
+};
+
+struct VSOutput {
+ float4 pos : SV_POSITION;
+ float2 uv;
+ float4 color;
+ float alpha;
+ uint32_t tex_id;
+};
+
+static const float2 square[6] = {
+ float2(-0.5, -0.5), // Top-left
+ float2(-0.5, 0.5), // Bottom-left
+ float2( 0.5, -0.5), // Top-right
+
+ float2( 0.5, -0.5), // Top-right
+ float2(-0.5, 0.5), // Bottom-left
+ float2( 0.5, 0.5) // Bottom-right
+};
+
+[shader ("vertex")]
+VSOutput main(VSInput input, uint vertex_index : SV_VertexID) {
+ VSOutput output;
+
+ float2 vertex_pos = square[vertex_index];
+ float2 final_pos = (vertex_pos * input.scale) + input.pos;
+
+ output.pos = float4(final_pos, 0.0, 1.0);
+ output.uv = input.uv;
+ output.color = input.color;
+ output.alpha = input.alpha;
+ output.tex_id = input.textureID;
+
+ return output;
+}
+
+[shader("fragment")]
+float4 main(VSOutput input) {
+
+ return float4(input.color.rgb, input.alpha);
+}