Compare commits

...

3 Commits

Author SHA1 Message Date
abdelrahman e3195c9b12 Load meshes and setup shader data buffers 2026-06-01 00:08:39 +01:00
abdelrahman 33fd5389aa Update profiles 2026-06-01 00:08:20 +01:00
abdelrahman 063b9a2adf Add assets 2026-06-01 00:08:08 +01:00
12 changed files with 8441 additions and 26 deletions
+61
View File
@@ -0,0 +1,61 @@
/* Copyright (c) 2025-2026, Sascha Willems
*
* SPDX-License-Identifier: MIT
*
*/
struct VSInput {
float3 Pos;
float3 Normal;
float2 UV;
};
Sampler2D textures[];
struct ShaderData {
float4x4 projection;
float4x4 view;
float4x4 model[3];
float4 lightPos;
uint32_t selected;
};
struct VSOutput {
float4 Pos : SV_POSITION;
float3 Normal;
float2 UV;
float3 Factor;
float3 LightVec;
float3 ViewVec;
uint32_t InstanceIndex;
};
[shader("vertex")]
VSOutput main(VSInput input, uniform ShaderData *shaderData, uint instanceIndex : SV_VulkanInstanceID) {
VSOutput output;
float4x4 modelMat = shaderData->model[instanceIndex];
output.Normal = mul((float3x3)mul(shaderData->view, modelMat), input.Normal);
output.UV = input.UV;
output.Pos = mul(shaderData->projection, mul(shaderData->view, mul(modelMat, float4(input.Pos.xyz, 1.0))));
output.Factor = (shaderData->selected == instanceIndex ? 3.0f : 1.0f);
output.InstanceIndex = instanceIndex;
// Calculate view vectors required for lighting
float4 fragPos = mul(mul(shaderData->view, modelMat), float4(input.Pos.xyz, 1.0));
output.LightVec = shaderData->lightPos.xyz - fragPos.xyz;
output.ViewVec = -fragPos.xyz;
return output;
}
[shader("fragment")]
float4 main(VSOutput input) {
// Phong lighting
float3 N = normalize(input.Normal);
float3 L = normalize(input.LightVec);
float3 V = normalize(input.ViewVec);
float3 R = reflect(-L, N);
float3 diffuse = max(dot(N, L), 0.0025);
float3 specular = pow(max(dot(R, V), 0.0), 16.0) * 0.75;
// Sample from texture
float3 color = textures[NonUniformResourceIndex(input.InstanceIndex)].Sample(input.UV).rgb * input.Factor;
return float4(diffuse * color.rgb + specular, 1.0);
}
+62
View File
@@ -0,0 +1,62 @@
# Blender 5.0.1 MTL File: 'suzanne4.blend'
# www.blender.org
newmtl Material
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Material.001
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.127605 0.127605 0.127605
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Material.002
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.000000 0.000000 0.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Material.003
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Material.004
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800007 0.200800 0.327761
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Material.005
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
+8150
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -2,5 +2,5 @@
bear -- clang++ -g -c -Wno-nullability-completeness -DVK_NO_PROTOTYPES -I$VULKAN_SDK/include vulkan_profiles/vulkan_profiles.cpp main.cpp
bear -a -- clang -g -c -DVK_NO_PROTOTYPES -Ivulkan_profiles -I$VULKAN_SDK/include $VULKAN_SDK/include/volk/volk.c wapp/wapp.c
bear -a -- clang++ -g -DVK_NO_PROTOTYPES -lSDL3 -lglm -o main *.o
bear -a -- clang++ -g -DVK_NO_PROTOTYPES -lSDL3 -lglm -ltinyobjloader -o main *.o
rm *.o
+136 -1
View File
@@ -2,19 +2,23 @@
#include "wapp/wapp.h"
#include "vulkan_profiles/vulkan_profiles.h"
#include <glm/ext/vector_int2.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <SDL3/SDL.h>
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_init.h>
#include <SDL3/SDL_keycode.h>
#include <SDL3/SDL_video.h>
#include <SDL3/SDL_vulkan.h>
#include <tiny_obj_loader.h>
#define VMA_IMPLEMENTATION
#include <vma/vk_mem_alloc.h>
#include <volk/volk.h>
#include <vulkan/vulkan.h>
#include <vulkan/vk_enum_string_helper.h>
#include <iostream>
#include <vector>
enum ExitCode {
EXIT_CODE_SUCCESS,
@@ -32,6 +36,28 @@ enum ExitCode {
EXIT_CODE_NO_QUEUE_FAMILIES,
EXIT_CODE_NO_SUITABLE_QUEUE_FAMILY,
EXIT_CODE_NO_SUITABLE_DEPTH_FORMAT,
EXIT_CODE_MESH_LOAD_FAILED,
};
struct Vertex {
glm::vec3 pos;
glm::vec3 normal;
glm::vec2 uv;
};
struct ShaderData {
glm::mat4 projection;
glm::mat4 view;
glm::mat4 model[3];
glm::vec4 light_pos{ 0.0f, -10.0f, 10.0f, 0.0f };
u32 selected{ 1 };
};
struct ShaderDataBuffer {
VmaAllocation allocation;
VmaAllocationInfo allocation_info;
VkBuffer buffer;
VkDeviceAddress device_address;
};
typedef VkPhysicalDevice *VkPhysicalDeviceArray;
@@ -39,11 +65,14 @@ typedef VkQueueFamilyProperties2 *VkQueueFamilyProperties2Array;
typedef VkImage *VkImageArray;
typedef VkImageView *VkImageViewArray;
typedef VkFormat *VkFormatArray;
typedef Vertex *VertexArray;
typedef ShaderDataBuffer *ShaderDataBufferArray;
wapp_intern inline void check(VkResult result);
wapp_intern inline void check_swapchain(VkResult result);
wapp_intern inline void check(bool result, i32 code);
wapp_intern constexpr u32 max_frames_in_flight = 2;
wapp_intern bool running = true;
wapp_intern bool update_swapchain = false;
wapp_intern f32 display_scale = 1.0f;
@@ -70,6 +99,10 @@ wapp_intern VkFormat depth_format = VK_FORMAT_UNDEFINED;
wapp_intern VkImage depth_image = VK_NULL_HANDLE;
wapp_intern VkImageView depth_view = VK_NULL_HANDLE;
wapp_intern VmaAllocation depth_allocation = VK_NULL_HANDLE;
wapp_intern VkBuffer vert_index_buf = VK_NULL_HANDLE;
wapp_intern VmaAllocation vert_index_buf_alloc = VK_NULL_HANDLE;
wapp_intern ShaderData shader_data = {};
wapp_intern ShaderDataBufferArray shader_data_bufs;
int main() {
// {{{ Initialisation
@@ -407,6 +440,104 @@ int main() {
// }}}
// }}}
wapp_mem_arena_allocator_temp_begin(&arena);
// {{{ Mesh Loading
// {{{ Load Mesh Data
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
check(tinyobj::LoadObj(&attrib, &shapes, &materials, nullptr, nullptr, "assets/suzanne.obj"),
EXIT_CODE_MESH_LOAD_FAILED);
const VkDeviceSize index_count = shapes[0].mesh.indices.size();
VertexArray vertices = wapp_array_alloc_capacity(Vertex, &arena, 128, ARRAY_INIT_NONE);
U16Array indices = wapp_array_alloc_capacity(u16, &arena, 128, ARRAY_INIT_NONE);
for (tinyobj::index_t &index : shapes[0].mesh.indices) {
Vertex v = {};
v.pos = {
attrib.vertices[index.vertex_index * 3],
-attrib.vertices[index.vertex_index * 3 + 1],
attrib.vertices[index.vertex_index * 3 + 2]
};
v.normal = {
attrib.normals[index.normal_index * 3],
-attrib.normals[index.normal_index * 3 + 1],
attrib.normals[index.normal_index * 3 + 2]
};
v.uv = {
attrib.texcoords[index.texcoord_index * 2],
1.0 - attrib.texcoords[index.texcoord_index * 2 + 1]
};
u16 idx = (u16)wapp_array_count(indices);
wapp_array_append_alloc(Vertex, &arena, vertices, &v, ARRAY_INIT_NONE);
wapp_array_append_alloc(u16, &arena, indices, &idx, ARRAY_INIT_NONE);
}
// }}}
// {{{ Upload to GPU
VkDeviceSize vertex_buf_size = sizeof(Vertex) * wapp_array_count(vertices);
VkDeviceSize index_buf_size = sizeof(u16) * wapp_array_count(vertices);
VkBufferCreateInfo buf_create_info = {};
buf_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buf_create_info.size = vertex_buf_size + index_buf_size;
buf_create_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
VmaAllocationCreateInfo buf_alloc_create_info = {};
buf_alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT;
buf_alloc_create_info.usage = VMA_MEMORY_USAGE_AUTO;
VmaAllocationInfo buf_alloc_info = {};
check(vmaCreateBuffer(allocator, &buf_create_info, &buf_alloc_create_info, &vert_index_buf,
&vert_index_buf_alloc, &buf_alloc_info));
memcpy(buf_alloc_info.pMappedData, vertices, vertex_buf_size);
memcpy((void *)((u8 *)buf_alloc_info.pMappedData + vertex_buf_size), indices, index_buf_size);
// }}}
// }}}
wapp_mem_arena_allocator_temp_end(&arena);
// {{{ Shader Data Buffers
shader_data_bufs = wapp_array_with_capacity(ShaderDataBuffer, 3, ARRAY_INIT_FILLED);
for (u32 i = 0; i < max_frames_in_flight; ++i) {
// {{{ Create Buffer
VkBufferUsageFlags2CreateInfo data_buf_usage_flags = {};
data_buf_usage_flags.sType = VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO;
data_buf_usage_flags.usage = VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT;
VkBufferCreateInfo data_buf_create_info = {};
data_buf_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
data_buf_create_info.size = sizeof(ShaderData);
data_buf_create_info.usage = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
data_buf_create_info.pNext = &data_buf_usage_flags;
VmaAllocationCreateInfo data_buf_alloc_create_info = {};
data_buf_alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT;
data_buf_create_info.usage = VMA_MEMORY_USAGE_AUTO;
check(vmaCreateBuffer(allocator, &data_buf_create_info, &data_buf_alloc_create_info,
&shader_data_bufs[i].buffer, &shader_data_bufs[i].allocation,
&shader_data_bufs[i].allocation_info));
// }}}
// {{{ Get Buffer GPU Address
VkBufferDeviceAddressInfo buf_dev_addr_info = {};
buf_dev_addr_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
buf_dev_addr_info.buffer = shader_data_bufs[i].buffer;
shader_data_bufs[i].device_address = vkGetBufferDeviceAddress(device, &buf_dev_addr_info);
// }}}
}
// }}}
// {{{ Render Loop
SDL_Event event = {};
while (running) {
@@ -426,6 +557,10 @@ int main() {
// }}}
// {{{ Cleanup
for (u32 i = 0; i < max_frames_in_flight; ++i) {
vmaDestroyBuffer(allocator, shader_data_bufs[i].buffer, shader_data_bufs[i].allocation);
}
vmaDestroyBuffer(allocator, vert_index_buf, vert_index_buf_alloc);
vkDestroyImageView(device, depth_view, nullptr);
vmaDestroyImage(allocator, depth_image, depth_allocation);
for (u32 i = 0; i < swapchain_image_count; ++i) {
+2 -1
View File
@@ -5,7 +5,8 @@
"extensions": {
"VK_KHR_global_priority": 1,
"VK_KHR_get_surface_capabilities2": 1,
"VK_KHR_swapchain": 70
"VK_KHR_swapchain": 70,
"VK_KHR_maintenance5": 1
},
"features": {
"VkPhysicalDeviceFeatures": {
+2
View File
@@ -440,6 +440,7 @@ static const VkExtensionProperties instanceExtensions[] = {
static const VkExtensionProperties deviceExtensions[] = {
VkExtensionProperties{ VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME, 1 },
VkExtensionProperties{ VK_KHR_MAINTENANCE_5_EXTENSION_NAME, 1 },
VkExtensionProperties{ VK_KHR_SWAPCHAIN_EXTENSION_NAME, 70 },
};
@@ -645,6 +646,7 @@ static const VkExtensionProperties instanceExtensions[] = {
static const VkExtensionProperties deviceExtensions[] = {
VkExtensionProperties{ VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME, 1 },
VkExtensionProperties{ VK_KHR_MAINTENANCE_5_EXTENSION_NAME, 1 },
VkExtensionProperties{ VK_KHR_SWAPCHAIN_EXTENSION_NAME, 70 },
};
+1
View File
@@ -33,6 +33,7 @@
#if defined(VK_VERSION_1_3) && \
defined(VK_KHR_get_surface_capabilities2) && \
defined(VK_KHR_global_priority) && \
defined(VK_KHR_maintenance5) && \
defined(VK_KHR_swapchain)
#define VP_LEARN_how_to_vulkan_2026 1
#define VP_LEARN_HOW_TO_VULKAN_2026_NAME "VP_LEARN_how_to_vulkan_2026"
+3
View File
@@ -41,6 +41,7 @@
#if defined(VK_VERSION_1_3) && \
defined(VK_KHR_get_surface_capabilities2) && \
defined(VK_KHR_global_priority) && \
defined(VK_KHR_maintenance5) && \
defined(VK_KHR_swapchain)
#define VP_LEARN_how_to_vulkan_2026 1
#define VP_LEARN_HOW_TO_VULKAN_2026_NAME "VP_LEARN_how_to_vulkan_2026"
@@ -841,6 +842,7 @@ static const VkExtensionProperties instanceExtensions[] = {
static const VkExtensionProperties deviceExtensions[] = {
VkExtensionProperties{ VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME, 1 },
VkExtensionProperties{ VK_KHR_MAINTENANCE_5_EXTENSION_NAME, 1 },
VkExtensionProperties{ VK_KHR_SWAPCHAIN_EXTENSION_NAME, 70 },
};
@@ -1046,6 +1048,7 @@ static const VkExtensionProperties instanceExtensions[] = {
static const VkExtensionProperties deviceExtensions[] = {
VkExtensionProperties{ VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME, 1 },
VkExtensionProperties{ VK_KHR_MAINTENANCE_5_EXTENSION_NAME, 1 },
VkExtensionProperties{ VK_KHR_SWAPCHAIN_EXTENSION_NAME, 70 },
};