KDGpu::Swapchain
Module: Public API
Manages presentation images for displaying rendered content to a window. More...
#include <KDGpu/swapchain.h>
Public Functions
Friends
Detailed Description
Manages presentation images for displaying rendered content to a window.
Vulkan equivalent:VkSwapchainKHR
Swapchain owns a collection of presentable images (textures) that are displayed to a Surface. It manages double/triple buffering and handles image acquisition and presentation.
Key features:
- Multiple presentation images for buffering
- Automatic image rotation and synchronization
- Format and resolution configuration
- VSync and presentation modes
Lifetime: Swapchains are created by Device from a Surface and should remain valid while presenting. They use RAII and clean up automatically.
Usage
Creating a swapchain:
1
2
3
4
5
6
7
8
9
10
11
12
13 | KDGpu::Surface surface = instance.createSurface(surfaceOptions);
KDGpu::Adapter *adapter = instance.selectAdapter(KDGpu::AdapterDeviceType::Default);
// Query surface capabilities
auto swapchainProps = adapter->swapchainProperties(surface);
KDGpu::Swapchain swapchain = device.createSwapchain(KDGpu::SwapchainOptions{
.surface = surface,
.format = swapchainProps.formats[0].format, // Choose first available
.minImageCount = 3, // Triple buffering
.imageExtent = { windowWidth, windowHeight },
.imageUsageFlags = KDGpu::TextureUsageFlagBits::ColorAttachmentBit,
});
|
Filename: kdgpu_doc_snippets.cpp
Accessing swapchain images:
| const std::vector<KDGpu::Texture> &images = swapchain.textures();
// Create views for rendering
std::vector<KDGpu::TextureView> imageViews;
for (const auto &image : images) {
imageViews.push_back(image.createView());
}
|
Filename: kdgpu_doc_snippets.cpp
Render loop with swapchain:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 | KDGpu::GpuSemaphore imageAvailable = device.createGpuSemaphore();
KDGpu::GpuSemaphore renderComplete = device.createGpuSemaphore();
KDGpu::CommandRecorder recorder = device.createCommandRecorder();
while (rendering) {
// Acquire next image to render to
uint32_t imageIndex;
const KDGpu::AcquireImageResult result = swapchain.getNextImageIndex(imageIndex, imageAvailable);
if (result != KDGpu::AcquireImageResult::Success) {
// Handle swapchain out of date (window resize, etc.)
continue;
}
// Record rendering commands to swapchain image
auto renderPass = recorder.beginRenderPass(KDGpu::RenderPassCommandRecorderOptions{
.colorAttachments = {
{
.view = imageViews[imageIndex],
.loadOperation = KDGpu::AttachmentLoadOperation::Clear,
.storeOperation = KDGpu::AttachmentStoreOperation::Store,
.clearValue = { 0.1f, 0.1f, 0.1f, 1.0f },
},
},
});
// ... render commands ...
renderPass.end();
KDGpu::CommandBuffer cmdBuffer = recorder.finish();
// Submit rendering
queue.submit(KDGpu::SubmitOptions{
.commandBuffers = { cmdBuffer },
.waitSemaphores = { imageAvailable.handle() },
.signalSemaphores = { renderComplete.handle() },
});
// Present the rendered image
queue.present(KDGpu::PresentOptions{
.waitSemaphores = { renderComplete.handle() },
.swapchainInfos = {
{
.swapchain = swapchain.handle(),
.imageIndex = imageIndex,
},
},
});
}
|
Filename: kdgpu_doc_snippets.cpp
Handling window resize:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | // Wait for GPU to finish using swapchain
device.waitUntilIdle();
// Destroy old image views
imageViews.clear();
// Recreate swapchain with new size
swapchain = device.createSwapchain(KDGpu::SwapchainOptions{
.surface = surface,
.format = surfaceFormat,
.minImageCount = 3,
.imageExtent = { newWidth, newHeight },
.imageUsageFlags = KDGpu::TextureUsageFlagBits::ColorAttachmentBit,
});
// Recreate views
for (const KDGpu::Texture &image : swapchain.textures()) {
imageViews.push_back(image.createView());
}
|
Filename: kdgpu_doc_snippets.cpp
Choosing presentation mode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | // Find best presentation mode
KDGpu::PresentMode presentMode = KDGpu::PresentMode::Fifo; // VSync (always available)
for (const auto &mode : swapchainProps.presentModes) {
if (mode == KDGpu::PresentMode::Mailbox) {
// Triple buffering without tearing
presentMode = mode;
break;
} else if (mode == KDGpu::PresentMode::Immediate) {
// No VSync, potential tearing
presentMode = mode;
}
}
KDGpu::Swapchain swapchainWithMode = device.createSwapchain(KDGpu::SwapchainOptions{
.surface = surface.handle(),
.format = surfaceFormat,
.imageExtent = { newWidth, newHeight },
.presentMode = presentMode,
});
|
Filename: kdgpu_doc_snippets.cpp
Getting swapchain optimal format:
| auto props = adapter->swapchainProperties(surface.handle());
// Find SRGB format if available
KDGpu::Format chosenFormat = props.formats[0].format;
for (const auto &formatInfo : props.formats) {
if (formatInfo.format == KDGpu::Format::B8G8R8A8_SRGB) {
chosenFormat = formatInfo.format;
break;
}
}
|
Filename: kdgpu_doc_snippets.cpp
Vulkan mapping:
See also:
Surface, Texture, Queue, Device
KDGpu API Overview
KDGpu to Vulkan API Mapping
Public Functions Documentation
function Swapchain
function ~Swapchain
function Swapchain
| Swapchain(
Swapchain && other
)
|
function operator=
| Swapchain & operator=(
Swapchain && other
)
|
function Swapchain
| Swapchain(
const Swapchain &
) =delete
|
function operator=
| Swapchain & operator=(
const Swapchain &
) =delete
|
function handle
| inline const Handle< Swapchain_t > & handle() const
|
function isValid
| inline bool isValid() const
|
function operator Handle< Swapchain_t >
| inline operator Handle< Swapchain_t >() const
|
function textures
| inline const std::vector< Texture > & textures() const
|
function getNextImageIndex
| AcquireImageResult getNextImageIndex(
uint32_t & imageIndex,
const Handle< GpuSemaphore_t > & semaphore =Handle< GpuSemaphore_t >()
)
|
Friends
friend Device
| friend class Device(
Device
);
|
Updated on 2026-03-31 at 00:02:07 +0000