<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/i-tried-coding-my-own-graphics-library-bmf3mtw79" -->

---
title: I Tried Coding my own Graphics Library | daily.dev
description: A developer builds a lightweight rendering library from scratch using Vulkan and C++, documenting the journey from creating a basic window with GLFW to...
canonical: https://daily.dev/posts/i-tried-coding-my-own-graphics-library-bmf3mtw79
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: I Tried Coding my own Graphics Library | daily.dev
og:description: A developer builds a lightweight rendering library from scratch using Vulkan and C++, documenting the journey from creating a basic window with GLFW to...
og:url: https://daily.dev/posts/i-tried-coding-my-own-graphics-library-bmf3mtw79
og:image: https://api.daily.dev/og/posts/bmF3mtw79.png
og:image:alt: I Tried Coding my own Graphics Library
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# I Tried Coding my own Graphics Library

**[Sebastian Lague](https://daily.dev/sources/sebastianlague)** · 27 min read · 3 upvotes · 0 comments

## Summary

A developer builds a lightweight rendering library from scratch using Vulkan and C++, documenting the journey from creating a basic window with GLFW to rendering 3D models, implementing compute shaders for GPU-based simulations, and exposing a C/C# API. Key topics covered include swap chains, frames in flight, synchronization primitives, depth buffering, perspective projection, instanced rendering, and compute shaders for fluid and particle simulations. The project also ports a text renderer and fluid simulation, comparing performance against Unity. The result is a functional version-zero graphics library with graphics and compute pipelines working end-to-end.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://www.youtube.com/watch?v=_JGMgpyCTsY>

## Questions this post answers

### How many frames in flight are typically used to overlap CPU and GPU work in a Vulkan renderer?

Two frames in flight is a common approach, where the CPU records commands for one frame into a separate command buffer while the GPU executes the previous frame's commands, avoiding writing to a buffer the GPU is still using. Fences signal when the CPU is free to reuse a buffer, and if the GPU isn't done in time, the CPU waits.

_Explore daily.dev for more deep dives into synchronization patterns when building your own renderer._

### How can I run a large-scale physics simulation like gravitational attraction between thousands of objects on the GPU instead of the CPU?

Use a compute shader that runs the simulation function once per object in parallel, typically with a thread group size like 64 threads, and include bounds checks so threads beyond the actual object count don't write to invalid memory. Data is read and written through a buffer accessed via its GPU memory address rather than named CPU-side variables, letting simulations like gravity or fluid dynamics scale to 100,000+ objects while rendering still runs smoothly.

_Follow along on daily.dev when weighing CPU versus GPU compute for your own particle or physics simulations._

### Why would a Vulkan renderer's triangles show through to the back side or render with the wrong depth ordering?

This typically happens when the depth buffer configuration or triangle winding order is wrong, causing the far side of a mesh to render on top of the near side. Fixing it requires enabling and correctly configuring a depth image during pipeline creation, remapping Z coordinates into a valid 0-to-1 depth range, and ensuring triangle winding order (clockwise vs counter-clockwise) matches the pipeline's culling settings.

_Check daily.dev for practical debugging notes when depth or culling issues crop up in your own Vulkan project._

## Similar posts on daily.dev

- [Software rendering in 500 lines of bare C\+\+](https://daily.dev/posts/software-rendering-in-500-lines-of-bare-c--8zxoc44yj) · Hacker News · 0 upvotes · 0 comments
- [Graphics Programming weekly - Issue 455 - September 13th, 2026](https://daily.dev/posts/graphics-programming-weekly---issue-455---september-13th-2026-6fernq5vz) · Jendrik Illner · 0 upvotes · 0 comments

---

Tags: [#gpu](https://daily.dev/tags/gpu), [#c++](https://daily.dev/tags/c++), [#vulkan](https://daily.dev/tags/vulkan), [#graphics-programming](https://daily.dev/tags/graphics-programming)

[View this post on daily.dev](https://daily.dev/posts/i-tried-coding-my-own-graphics-library-bmf3mtw79)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"I Tried Coding my own Graphics Library","url":"https://daily.dev/posts/i-tried-coding-my-own-graphics-library-bmf3mtw79","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/i-tried-coding-my-own-graphics-library-bmf3mtw79"},"datePublished":"2026-07-25T13:13:35.291Z","dateModified":"2026-09-14T08:17:34.537Z","description":"A developer builds a lightweight rendering library from scratch using Vulkan and C++, documenting the journey from creating a basic window with GLFW to...","image":"https://i.ytimg.com/vi/_JGMgpyCTsY/sddefault.jpg","thumbnailUrl":"https://i.ytimg.com/vi/_JGMgpyCTsY/sddefault.jpg","isAccessibleForFree":true,"articleSection":"Sebastian Lague","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Sebastian Lague","logo":"https://media.daily.dev/image/upload/s--rxa5CpKA--/f_auto/v1727446540/logos/sebastianlague","url":"https://daily.dev/sources/sebastianlague"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/i-tried-coding-my-own-graphics-library-bmf3mtw79","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":3},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"gpu,c++,vulkan,graphics-programming","timeRequired":"PT27M","video":{"@type":"VideoObject","name":"I Tried Coding my own Graphics Library","description":"A developer builds a lightweight rendering library from scratch using Vulkan and C++, documenting the journey from creating a basic window with GLFW to...","thumbnailUrl":"https://i.ytimg.com/vi/_JGMgpyCTsY/sddefault.jpg","uploadDate":"2026-07-25T13:13:35.291Z","duration":"PT27M","url":"https://api.daily.dev/r/bmF3mtw79","embedUrl":"https://www.youtube.com/embed/_JGMgpyCTsY"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Sebastian Lague","item":"https://daily.dev/sources/sebastianlague"},{"@type":"ListItem","position":3,"name":"I Tried Coding my own Graphics Library"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/i-tried-coding-my-own-graphics-library-bmf3mtw79#faq","mainEntity":[{"@type":"Question","name":"How many frames in flight are typically used to overlap CPU and GPU work in a Vulkan renderer?","acceptedAnswer":{"@type":"Answer","text":"Two frames in flight is a common approach, where the CPU records commands for one frame into a separate command buffer while the GPU executes the previous frame's commands, avoiding writing to a buffer the GPU is still using. Fences signal when the CPU is free to reuse a buffer, and if the GPU isn't done in time, the CPU waits. Explore daily.dev for more deep dives into synchronization patterns when building your own renderer."}},{"@type":"Question","name":"How can I run a large-scale physics simulation like gravitational attraction between thousands of objects on the GPU instead of the CPU?","acceptedAnswer":{"@type":"Answer","text":"Use a compute shader that runs the simulation function once per object in parallel, typically with a thread group size like 64 threads, and include bounds checks so threads beyond the actual object count don't write to invalid memory. Data is read and written through a buffer accessed via its GPU memory address rather than named CPU-side variables, letting simulations like gravity or fluid dynamics scale to 100,000+ objects while rendering still runs smoothly. Follow along on daily.dev when weighing CPU versus GPU compute for your own particle or physics simulations."}},{"@type":"Question","name":"Why would a Vulkan renderer's triangles show through to the back side or render with the wrong depth ordering?","acceptedAnswer":{"@type":"Answer","text":"This typically happens when the depth buffer configuration or triangle winding order is wrong, causing the far side of a mesh to render on top of the near side. Fixing it requires enabling and correctly configuring a depth image during pipeline creation, remapping Z coordinates into a valid 0-to-1 depth range, and ensuring triangle winding order (clockwise vs counter-clockwise) matches the pipeline's culling settings. Check daily.dev for practical debugging notes when depth or culling issues crop up in your own Vulkan project."}}]}
```

