Fix leaky abstractions
This commit is contained in:
+27
-161
@@ -6,9 +6,6 @@
|
||||
#define PR_RHI_VULKAN
|
||||
|
||||
#include "prism/rhi/pr_rhi.h"
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <ktx.h>
|
||||
#include <ktxvulkan.h>
|
||||
#include <SDL3/SDL_timer.h>
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
@@ -19,7 +16,6 @@
|
||||
#include <SDL3/SDL_init.h>
|
||||
#include <SDL3/SDL_keycode.h>
|
||||
#include <SDL3/SDL_video.h>
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
#include <slang/slang.h>
|
||||
#include <slang/slang-com-ptr.h>
|
||||
#include <tiny_obj_loader.h>
|
||||
@@ -27,26 +23,6 @@
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
// ============================================================================
|
||||
// Helpers
|
||||
// ============================================================================
|
||||
|
||||
static PrRhiFormat _fromVkFormat(VkFormat fmt) {
|
||||
switch (fmt) {
|
||||
case VK_FORMAT_R8G8B8A8_SRGB: return PR_RHI_FORMAT_R8G8B8A8_SRGB;
|
||||
case VK_FORMAT_R8G8B8A8_UNORM: return PR_RHI_FORMAT_R8G8B8A8_UNORM;
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT: return PR_RHI_FORMAT_R16G16B16A16_SFLOAT;
|
||||
case VK_FORMAT_R32G32B32A32_SFLOAT: return PR_RHI_FORMAT_R32G32B32A32_SFLOAT;
|
||||
case VK_FORMAT_R32G32B32_SFLOAT: return PR_RHI_FORMAT_R32G32B32_SFLOAT;
|
||||
case VK_FORMAT_R32G32_SFLOAT: return PR_RHI_FORMAT_R32G32_SFLOAT;
|
||||
case VK_FORMAT_R32_SFLOAT: return PR_RHI_FORMAT_R32_SFLOAT;
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT: return PR_RHI_FORMAT_D24_UNORM_S8_UINT;
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT: return PR_RHI_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
case VK_FORMAT_B8G8R8A8_SRGB: return PR_RHI_FORMAT_B8G8R8A8_SRGB;
|
||||
default: return PR_RHI_FORMAT_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Exit codes
|
||||
// ============================================================================
|
||||
@@ -153,88 +129,6 @@ struct AppState {
|
||||
Slang::ComPtr<slang::IGlobalSession> slang_session;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Helpers
|
||||
// ============================================================================
|
||||
|
||||
static void _uploadTexture(AppState *app, PrRhiTexture *tex,
|
||||
ktxTexture *ktx_tex, WpAllocator *scratch) {
|
||||
// Create staging buffer
|
||||
PrRhiBufferDesc staging_desc = {};
|
||||
staging_desc.size = (u32)ktx_tex->dataSize;
|
||||
staging_desc.usage = PR_RHI_BUFFER_USAGE_TRANSFER_SRC;
|
||||
staging_desc.memory = PR_RHI_MEMORY_CPU_TO_GPU;
|
||||
|
||||
PrRhiBuffer *staging = prRhiCreateBuffer(app->device, staging_desc, scratch);
|
||||
void *data = prRhiBufferMap(app->device, staging);
|
||||
memcpy(data, ktx_tex->pData, ktx_tex->dataSize);
|
||||
prRhiBufferUnmap(app->device, staging);
|
||||
|
||||
// Create fence
|
||||
PrRhiFenceDesc fence_desc = {};
|
||||
fence_desc.signaled = false;
|
||||
PrRhiFence *fence = prRhiCreateFence(app->device, fence_desc, scratch);
|
||||
|
||||
// Allocate temporary command buffer
|
||||
PrRhiCommandBufferArray tmp_cbs = prRhiAllocateCommandBuffers(app->device,
|
||||
app->cmd_pool, 1, scratch);
|
||||
PrRhiCommandBuffer *cb = tmp_cbs[0];
|
||||
|
||||
prRhiBeginCommandBuffer(cb);
|
||||
|
||||
// Transition UNDEFINED → TRANSFER_DST
|
||||
PrRhiImageMemoryBarrier barrier_to_transfer = {};
|
||||
barrier_to_transfer.texture = tex;
|
||||
barrier_to_transfer.old_layout = PR_RHI_LAYOUT_UNDEFINED;
|
||||
barrier_to_transfer.new_layout = PR_RHI_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barrier_to_transfer.src_stage_mask = (u64)VK_PIPELINE_STAGE_2_NONE;
|
||||
barrier_to_transfer.src_access_mask = 0;
|
||||
barrier_to_transfer.dst_stage_mask = (u64)VK_PIPELINE_STAGE_2_TRANSFER_BIT;
|
||||
barrier_to_transfer.dst_access_mask = (u64)VK_ACCESS_2_TRANSFER_WRITE_BIT;
|
||||
prRhiCmdPipelineBarrier(cb, wpArray(PrRhiImageMemoryBarrier, barrier_to_transfer), NULL);
|
||||
|
||||
// Copy all mip levels
|
||||
PrRhiBufferImageCopyArray copies = wpArrayAllocCapacity(PrRhiBufferImageCopy, scratch,
|
||||
ktx_tex->numLevels, WP_ARRAY_INIT_NONE);
|
||||
for (u32 j = 0; j < ktx_tex->numLevels; ++j) {
|
||||
ktx_size_t mip_offset = 0;
|
||||
ktxTexture_GetImageOffset(ktx_tex, j, 0, 0, &mip_offset);
|
||||
|
||||
PrRhiBufferImageCopy copy = {};
|
||||
copy.buffer_offset = mip_offset;
|
||||
copy.mip_level = j;
|
||||
copy.width = ktx_tex->baseWidth >> j;
|
||||
copy.height = ktx_tex->baseHeight >> j;
|
||||
wpArrayAppendCapped(PrRhiBufferImageCopy, copies, ©);
|
||||
}
|
||||
|
||||
prRhiCmdCopyBufferToImage(cb, staging, tex, copies);
|
||||
wpArrayDealloc(PrRhiBufferImageCopy, scratch, &copies);
|
||||
|
||||
// Transition TRANSFER_DST → READ_ONLY
|
||||
PrRhiImageMemoryBarrier barrier_to_read = {};
|
||||
barrier_to_read.texture = tex;
|
||||
barrier_to_read.old_layout = PR_RHI_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barrier_to_read.new_layout = PR_RHI_LAYOUT_READ_ONLY_OPTIMAL;
|
||||
barrier_to_read.src_stage_mask = (u64)VK_PIPELINE_STAGE_2_TRANSFER_BIT;
|
||||
barrier_to_read.src_access_mask = (u64)VK_ACCESS_2_TRANSFER_WRITE_BIT;
|
||||
barrier_to_read.dst_stage_mask = (u64)VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
barrier_to_read.dst_access_mask = (u64)VK_ACCESS_2_SHADER_READ_BIT;
|
||||
prRhiCmdPipelineBarrier(cb, wpArray(PrRhiImageMemoryBarrier, barrier_to_read), NULL);
|
||||
|
||||
prRhiEndCommandBuffer(cb);
|
||||
|
||||
// Submit and wait
|
||||
prRhiQueueSubmit(app->device, cb, NULL, NULL, fence);
|
||||
prRhiWaitForFences(app->device, wpArray(PrRhiFence *, fence), 1, true, UINT64_MAX);
|
||||
|
||||
// Cleanup
|
||||
prRhiDestroyFence(app->device, fence, scratch);
|
||||
prRhiFreeCommandBuffers(app->device, app->cmd_pool, 1, tmp_cbs);
|
||||
wpArrayDealloc(PrRhiCommandBuffer *, scratch, &tmp_cbs);
|
||||
prRhiDestroyBuffer(app->device, staging, scratch);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Main
|
||||
// ============================================================================
|
||||
@@ -245,7 +139,6 @@ int main() {
|
||||
|
||||
// {{{ Initialisation
|
||||
check(SDL_Init(SDL_INIT_VIDEO), EXIT_CODE_SDL_INIT_FAILED);
|
||||
check(SDL_Vulkan_LoadLibrary(nullptr), EXIT_CODE_VULKAN_LIB_LOAD_FAILED);
|
||||
|
||||
f32 display_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
|
||||
app.window = SDL_CreateWindow("How To Vulkan (Prism)", (i32)(display_scale * 1920),
|
||||
@@ -255,18 +148,9 @@ int main() {
|
||||
// }}}
|
||||
|
||||
// {{{ Instance creation
|
||||
u32 ext_count = 0;
|
||||
const char *const *exts = SDL_Vulkan_GetInstanceExtensions(&ext_count);
|
||||
|
||||
WpAllocator scratch = wpMemArenaAllocatorInitZero(MiB(64));
|
||||
|
||||
PrRhiExtensionArray extensions = wpArrayAllocCapacity(const char *, &scratch, ext_count, WP_ARRAY_INIT_NONE);
|
||||
for (u32 i = 0; i < ext_count; ++i) {
|
||||
wpArrayAppendCapped(const char *, extensions, &exts[i]);
|
||||
}
|
||||
|
||||
PrRhiInstanceDesc inst_desc = {};
|
||||
inst_desc.extra_extensions = extensions;
|
||||
app.inst = prRhiCreateInstance(inst_desc, &arena);
|
||||
// }}}
|
||||
|
||||
@@ -279,11 +163,12 @@ int main() {
|
||||
PrRhiPhysicalDeviceProperties props;
|
||||
prRhiGetPhysicalDeviceProperties(pdevs[i], &props);
|
||||
switch (props.device_type) {
|
||||
case 1: // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
|
||||
case 2: // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
|
||||
if (props.api_version >= VK_API_VERSION_1_3) {
|
||||
case PR_RHI_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
|
||||
selected = (i32)i;
|
||||
break;
|
||||
case PR_RHI_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
|
||||
if (selected == -1)
|
||||
selected = (i32)i;
|
||||
}
|
||||
break;
|
||||
default: continue;
|
||||
}
|
||||
@@ -300,13 +185,9 @@ int main() {
|
||||
// }}}
|
||||
|
||||
// {{{ Surface creation
|
||||
VkSurfaceKHR vk_surface = VK_NULL_HANDLE;
|
||||
VkInstance vk_inst = (VkInstance)prRhiGetNativeInstanceHandle(app.inst);
|
||||
check(SDL_Vulkan_CreateSurface(app.window, vk_inst, nullptr, &vk_surface),
|
||||
EXIT_CODE_SURFACE_CREATION_FAILED);
|
||||
check(SDL_GetWindowSize(app.window, &app.window_size.x, &app.window_size.y),
|
||||
EXIT_CODE_GET_WINDOW_SIZE_FAILED);
|
||||
app.surface = prRhiCreateSurface(app.inst, (void *)vk_surface, &arena);
|
||||
app.surface = prRhiCreateSurfaceFromWindow(app.inst, (void *)app.window, &arena);
|
||||
// }}}
|
||||
|
||||
// {{{ Device creation
|
||||
@@ -441,28 +322,13 @@ int main() {
|
||||
app.textures = wpArrayAllocCapacity(TextureResources, &arena, AppState::texture_count,
|
||||
WP_ARRAY_INIT_FILLED);
|
||||
|
||||
PrRhiCommandBufferArray upload_cbs = prRhiAllocateCommandBuffers(app.device, app.cmd_pool, 1, &scratch);
|
||||
PrRhiCommandBuffer *upload_cb = upload_cbs[0];
|
||||
|
||||
for (u32 i = 0; i < AppState::texture_count; ++i) {
|
||||
// Load KTX
|
||||
ktxTexture *ktx_tex = nullptr;
|
||||
char buf[2048] = {};
|
||||
snprintf(buf, sizeof(buf), "assets/suzanne%u.ktx", i);
|
||||
ktxTexture_CreateFromNamedFile(buf, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktx_tex);
|
||||
|
||||
VkFormat vk_fmt = ktxTexture_GetVkFormat(ktx_tex);
|
||||
|
||||
// Create texture
|
||||
PrRhiTextureDesc tex_desc = {};
|
||||
tex_desc.format = _fromVkFormat(vk_fmt);
|
||||
tex_desc.width = (u32)ktx_tex->baseWidth;
|
||||
tex_desc.height = (u32)ktx_tex->baseHeight;
|
||||
tex_desc.mip_levels = (u32)ktx_tex->numLevels;
|
||||
tex_desc.usage = (PrRhiTextureUsage)(PR_RHI_TEXTURE_USAGE_TRANSFER_DST |
|
||||
PR_RHI_TEXTURE_USAGE_SAMPLED);
|
||||
|
||||
PrRhiTexture *tex = prRhiCreateTexture(app.device, tex_desc, &arena);
|
||||
|
||||
// Upload texture data
|
||||
_uploadTexture(&app, tex, ktx_tex, &scratch);
|
||||
PrRhiTexture *tex = prRhiCreateTextureFromKtx(app.device, buf, app.cmd_pool, upload_cb, &arena);
|
||||
|
||||
// Create sampler
|
||||
PrRhiSamplerDesc samp_desc = {};
|
||||
@@ -470,14 +336,15 @@ int main() {
|
||||
samp_desc.min_filter = PR_RHI_FILTER_LINEAR;
|
||||
samp_desc.mipmap_mode = PR_RHI_MIPMAP_MODE_LINEAR;
|
||||
samp_desc.max_anisotropy = 8.0f;
|
||||
samp_desc.max_lod = VK_LOD_CLAMP_NONE;
|
||||
samp_desc.max_lod = PR_RHI_LOD_CLAMP_NONE;
|
||||
PrRhiSampler *sampler = prRhiCreateSampler(app.device, samp_desc, &arena);
|
||||
|
||||
app.textures[i].texture = tex;
|
||||
app.textures[i].sampler = sampler;
|
||||
|
||||
ktxTexture_Destroy(ktx_tex);
|
||||
}
|
||||
|
||||
prRhiFreeCommandBuffers(app.device, app.cmd_pool, 1, upload_cbs);
|
||||
wpArrayDealloc(PrRhiCommandBuffer *, &scratch, &upload_cbs);
|
||||
// }}}
|
||||
|
||||
// {{{ Descriptor set layout, pool, set
|
||||
@@ -564,7 +431,7 @@ int main() {
|
||||
// {{{ Pipeline layout
|
||||
PrRhiPushConstantRange pc_range = {};
|
||||
pc_range.stage_flags = PR_RHI_SHADER_STAGE_VERTEX;
|
||||
pc_range.size = sizeof(u64); // VkDeviceAddress
|
||||
pc_range.size = sizeof(u64);
|
||||
|
||||
PrRhiDescriptorSetLayout *set_layouts_pl[] = { app.desc_set_layout };
|
||||
PrRhiDescriptorSetLayoutArray pl_layouts = wpArray(PrRhiDescriptorSetLayout *, set_layouts_pl[0]);
|
||||
@@ -677,20 +544,20 @@ int main() {
|
||||
img_barriers[0].texture = color_tex;
|
||||
img_barriers[0].old_layout = PR_RHI_LAYOUT_UNDEFINED;
|
||||
img_barriers[0].new_layout = PR_RHI_LAYOUT_ATTACHMENT_OPTIMAL;
|
||||
img_barriers[0].src_stage_mask = (u64)VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
img_barriers[0].src_access_mask = 0;
|
||||
img_barriers[0].dst_stage_mask = (u64)VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
img_barriers[0].dst_access_mask = (u64)(VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT);
|
||||
img_barriers[0].src_stage_mask = PR_RHI_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
|
||||
img_barriers[0].src_access_mask = PR_RHI_ACCESS_NONE;
|
||||
img_barriers[0].dst_stage_mask = PR_RHI_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
|
||||
img_barriers[0].dst_access_mask = (PrRhiAccess)(PR_RHI_ACCESS_COLOR_ATTACHMENT_READ | PR_RHI_ACCESS_COLOR_ATTACHMENT_WRITE);
|
||||
|
||||
// Depth attachment
|
||||
PrRhiTexture *depth_tex = prRhiGetSwapchainDepthTexture(app.swapchain);
|
||||
img_barriers[1].texture = depth_tex;
|
||||
img_barriers[1].old_layout = PR_RHI_LAYOUT_UNDEFINED;
|
||||
img_barriers[1].new_layout = PR_RHI_LAYOUT_ATTACHMENT_OPTIMAL;
|
||||
img_barriers[1].src_stage_mask = (u64)VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
|
||||
img_barriers[1].src_access_mask = (u64)VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
img_barriers[1].dst_stage_mask = (u64)VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT;
|
||||
img_barriers[1].dst_access_mask = (u64)VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
img_barriers[1].src_stage_mask = PR_RHI_PIPELINE_STAGE_LATE_FRAGMENT_TESTS;
|
||||
img_barriers[1].src_access_mask = PR_RHI_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE;
|
||||
img_barriers[1].dst_stage_mask = PR_RHI_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS;
|
||||
img_barriers[1].dst_access_mask = PR_RHI_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE;
|
||||
|
||||
PrRhiImageMemoryBarrierArray barriers_arr = wpArray(PrRhiImageMemoryBarrier,
|
||||
img_barriers[0], img_barriers[1]);
|
||||
@@ -749,10 +616,10 @@ int main() {
|
||||
present_barrier.texture = prRhiGetSwapchainTexture(app.swapchain, image_index);
|
||||
present_barrier.old_layout = PR_RHI_LAYOUT_ATTACHMENT_OPTIMAL;
|
||||
present_barrier.new_layout = PR_RHI_LAYOUT_PRESENT_SRC;
|
||||
present_barrier.src_stage_mask = (u64)VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
present_barrier.src_access_mask = (u64)VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
present_barrier.dst_stage_mask = (u64)VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
present_barrier.dst_access_mask = 0;
|
||||
present_barrier.src_stage_mask = PR_RHI_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
|
||||
present_barrier.src_access_mask = PR_RHI_ACCESS_COLOR_ATTACHMENT_WRITE;
|
||||
present_barrier.dst_stage_mask = PR_RHI_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
|
||||
present_barrier.dst_access_mask = PR_RHI_ACCESS_NONE;
|
||||
|
||||
prRhiCmdPipelineBarrier(cb, wpArray(PrRhiImageMemoryBarrier, present_barrier), NULL);
|
||||
}
|
||||
@@ -870,7 +737,6 @@ int main() {
|
||||
prRhiDestroyInstance(app.inst, &arena);
|
||||
|
||||
SDL_DestroyWindow(app.window);
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
SDL_Quit();
|
||||
|
||||
wpMemArenaAllocatorDestroy(&arena);
|
||||
|
||||
Reference in New Issue
Block a user