mirror of
https://github.com/simplysanatori/KartFrame.git
synced 2026-10-26 04:08:30 +01:00
KARTFRAME_FPSLOG=2 now times every set (game-frame and refresh sets) with in-pass timestamps per draw class (scene, HUD, fades, EFB effects, sink copy); frame/perf/gpuprof.py tabulates them. Eyes may render straight into the swapchain images (the bridge's DirectTargets); the Vulkan backend measures both ways on the first race sets and keeps the cheaper (KARTFRAME_DIRECT_EYES=0/1 forces). The native render of an immersive race frame stops after its last copy for the eyes on Linux too (KARTFRAME_MONO_FULL=1 keeps it whole) and is clipped to the copies' rectangles (KARTFRAME_NATIVE_CLIP=0). DisplayTimeNanos returns the converted CLOCK_MONOTONIC time directly (two clock reads put two stamps 0.24 ms off in the orchestrator's soak); the mock counts such offsets as 'between', honours MUTABLE_FORMAT. Not yet soaked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
118 lines
4.6 KiB
C++
118 lines
4.6 KiB
C++
#pragma once
|
|
|
|
#include <aurora/aurora.h>
|
|
#include <aurora/math.hpp>
|
|
|
|
#include "wgpu.hpp"
|
|
|
|
#include <array>
|
|
#include <cstdint>
|
|
|
|
struct SDL_Window;
|
|
|
|
namespace aurora::webgpu {
|
|
struct GraphicsConfig {
|
|
wgpu::SurfaceConfiguration surfaceConfiguration;
|
|
wgpu::TextureFormat depthFormat;
|
|
uint32_t msaaSamples;
|
|
uint16_t textureAnisotropy;
|
|
uint32_t maxTextureDimension2D;
|
|
};
|
|
struct TextureWithSampler {
|
|
wgpu::Texture texture;
|
|
wgpu::TextureView view;
|
|
wgpu::Extent3D size;
|
|
wgpu::TextureFormat format;
|
|
wgpu::Sampler sampler;
|
|
};
|
|
struct PresentSource {
|
|
wgpu::BindGroup bindGroup;
|
|
wgpu::Texture texture;
|
|
wgpu::Extent3D size;
|
|
wgpu::TextureFormat format;
|
|
};
|
|
struct Viewport {
|
|
float left;
|
|
float top;
|
|
float width;
|
|
float height;
|
|
float znear;
|
|
float zfar;
|
|
|
|
bool operator==(const Viewport& rhs) const {
|
|
return left == rhs.left && top == rhs.top && width == rhs.width && height == rhs.height && znear == rhs.znear &&
|
|
zfar == rhs.zfar;
|
|
}
|
|
bool operator!=(const Viewport& rhs) const { return !(*this == rhs); }
|
|
};
|
|
|
|
extern wgpu::Device g_device;
|
|
extern wgpu::Queue g_queue;
|
|
extern wgpu::Surface g_surface;
|
|
extern wgpu::BackendType g_backendType;
|
|
extern GraphicsConfig g_graphicsConfig;
|
|
extern TextureWithSampler g_frameBuffer;
|
|
extern TextureWithSampler g_frameBufferResolved;
|
|
extern TextureWithSampler g_depthBuffer;
|
|
extern wgpu::RenderPipeline g_CopyPipeline;
|
|
extern std::array<wgpu::RenderPipeline, 4> g_OrientedCopyPipelines;
|
|
extern bool g_RaceOutputNeedsCopy;
|
|
extern int g_RaceOutputCopyMode;
|
|
extern wgpu::BindGroup g_CopyBindGroup;
|
|
extern wgpu::Instance g_instance;
|
|
extern bool g_bcTexturesSupported;
|
|
// The device was created with TimestampQuery, so passes may carry timestamp writes (gfx::gpu_timing_*).
|
|
extern bool g_timestampQueriesSupported;
|
|
// Timestamps inside passes and on the encoder (Dawn experimental feature; KARTFRAME_FPSLOG=2 only).
|
|
extern bool g_timestampInsidePassesSupported;
|
|
|
|
bool initialize(AuroraBackend backend);
|
|
// KARTFRAME_HEADLESS=1: development runs without a presentable swapchain. The window and surface
|
|
// still exist (the adapter is chosen against it) but the swapchain is never configured; the desktop
|
|
// view renders into an offscreen texture that is never shown.
|
|
bool headless() noexcept;
|
|
wgpu::Texture headless_surface_texture();
|
|
void shutdown();
|
|
// Device-loss callbacks may run on a Dawn-managed thread and only publish loss state; frame
|
|
// threads call this at ordered boundaries to turn it into the one user-visible fatal error.
|
|
void fail_if_device_lost() noexcept;
|
|
void release_surface() noexcept;
|
|
bool refresh_surface(bool recreate = true);
|
|
void resize_swapchain(uint32_t width, uint32_t height, uint32_t native_width, uint32_t native_height,
|
|
bool force = false);
|
|
TextureWithSampler create_render_texture(uint32_t width, uint32_t height, bool multisampled);
|
|
const TextureWithSampler& present_source() noexcept;
|
|
PresentSource current_present_source() noexcept;
|
|
void set_present_source_override(wgpu::BindGroup bindGroup, wgpu::Texture texture, wgpu::Extent3D size,
|
|
wgpu::TextureFormat format) noexcept;
|
|
void clear_present_source_override() noexcept;
|
|
wgpu::BindGroup create_copy_bind_group(const TextureWithSampler& source);
|
|
wgpu::BindGroup create_copy_bind_group(wgpu::TextureView sourceView, wgpu::Sampler sampler);
|
|
Viewport calculate_present_viewport(uint32_t surface_width, uint32_t surface_height, uint32_t content_width,
|
|
uint32_t content_height) noexcept;
|
|
Viewport calculate_present_viewport_for_aspect(uint32_t surface_width, uint32_t surface_height,
|
|
float content_aspect) noexcept;
|
|
void draw_clear(const wgpu::RenderPassEncoder& pass, bool clearColor, bool clearAlpha, bool clearDepth,
|
|
const Vec4<float>& clearColorValue, float clearDepthValue);
|
|
|
|
size_t load_from_cache(void const* key, size_t keySize, void* value, size_t valueSize, void* userdata);
|
|
void store_to_cache(void const* key, size_t keySize, void const* value, size_t valueSize, void* userdata);
|
|
void cache_shutdown();
|
|
// Blocks until every blob Dawn has stored is committed to the cache database. Stores return
|
|
// once the blob is copied, so a caller that needs it on disk (a process about to end) waits here.
|
|
void flush_cache_writes();
|
|
|
|
struct BlobCacheStats {
|
|
uint64_t lookups;
|
|
uint64_t hits;
|
|
uint64_t stores;
|
|
uint64_t hitBytes;
|
|
// Stores of a large blob whose bytes matched what the database already holds.
|
|
uint64_t unchanged;
|
|
};
|
|
BlobCacheStats blob_cache_stats() noexcept;
|
|
// Persists the monolithic Vulkan pipeline cache into the blob cache (no-op elsewhere).
|
|
void serialize_pipeline_caches() noexcept;
|
|
|
|
} // namespace aurora::webgpu
|