Port hakuX Vulkan texture dirty-check fast path

This commit is contained in:
izzy2lost
2026-04-08 02:34:51 -04:00
parent 0182fcaf86
commit 6bb9cdb1b7
5 changed files with 63 additions and 3 deletions
+1
View File
@@ -164,6 +164,7 @@ void pgraph_vk_image_blit(NV2AState *d)
// download should be discarded.
surf_dest->download_pending = false;
surf_dest->draw_dirty = false;
surf_dest->download_generation = surf_dest->draw_generation;
}
surf_dest->upload_pending = true;
pg->draw_time++;
+6
View File
@@ -1952,12 +1952,18 @@ void pgraph_vk_set_surface_dirty(PGRAPHState *pg, bool color, bool zeta)
if (r->color_binding) {
r->color_binding->draw_dirty |= color;
if (color) {
r->color_binding->draw_generation++;
}
r->color_binding->frame_time = pg->frame_time;
r->color_binding->cleared = false;
}
if (r->zeta_binding) {
r->zeta_binding->draw_dirty |= zeta;
if (zeta) {
r->zeta_binding->draw_generation++;
}
r->zeta_binding->frame_time = pg->frame_time;
r->zeta_binding->cleared = false;
}
+4
View File
@@ -130,6 +130,8 @@ typedef struct SurfaceBinding {
bool draw_dirty;
bool download_pending;
bool upload_pending;
uint32_t draw_generation;
uint32_t download_generation;
BasicSurfaceFormatInfo fmt;
SurfaceFormatInfo host_fmt;
@@ -222,6 +224,8 @@ typedef struct TextureBinding {
uint64_t hash;
unsigned int draw_time;
uint32_t submit_time;
unsigned int dirty_check_frame;
bool dirty_check_result;
} TextureBinding;
typedef struct QueryReport {
+8
View File
@@ -478,6 +478,11 @@ static void download_surface(NV2AState *d, SurfaceBinding *surface, bool force)
return;
}
if (!surface->draw_dirty &&
surface->download_generation == surface->draw_generation) {
return;
}
// FIXME: Respect write enable at last TOU?
download_surface_to_buffer(d, surface, d->vram_ptr + surface->vram_addr);
@@ -491,6 +496,7 @@ static void download_surface(NV2AState *d, SurfaceBinding *surface, bool force)
surface->download_pending = false;
surface->draw_dirty = false;
surface->download_generation = surface->draw_generation;
}
void pgraph_vk_wait_for_surface_download(SurfaceBinding *surface)
@@ -1375,6 +1381,8 @@ static void populate_surface_binding_target_sized(NV2AState *d, bool color,
target->upload_pending = true;
target->download_pending = false;
target->draw_dirty = false;
target->draw_generation = 0;
target->download_generation = 0;
target->dma_addr = dma.address;
target->dma_len = dma.limit;
target->frame_time = pg->frame_time;
+44 -3
View File
@@ -1162,9 +1162,29 @@ static void create_texture(PGRAPHState *pg, int texture_idx)
}
if (!surface_to_texture && !possibly_dirty_checked) {
possibly_dirty |= check_texture_possibly_dirty(
d, texture_vram_offset, texture_length, texture_palette_vram_offset,
texture_palette_data_size);
bool skip_dirty_check = binding_found &&
snode->dirty_check_frame == pg->frame_time &&
!snode->dirty_check_result;
if (!skip_dirty_check) {
bool vram_dirty = check_texture_possibly_dirty(
d, texture_vram_offset, texture_length,
texture_palette_vram_offset, texture_palette_data_size);
possibly_dirty |= vram_dirty;
if (binding_found) {
snode->dirty_check_frame = pg->frame_time;
snode->dirty_check_result = vram_dirty;
}
}
}
if (binding_found && possibly_dirty && !surface_to_texture) {
bool vram_confirmed_clean =
snode->dirty_check_frame == pg->frame_time &&
!snode->dirty_check_result;
if (vram_confirmed_clean) {
snode->possibly_dirty = false;
possibly_dirty = false;
}
}
// Calculate hash of texture data, if necessary
@@ -1428,6 +1448,24 @@ void pgraph_vk_bind_textures(NV2AState *d)
return;
}
for (int i = 0; i < NV2A_MAX_TEXTURES; i++) {
TextureBinding *binding = r->texture_bindings[i];
if (!binding || binding == &r->dummy_texture || !binding->possibly_dirty
|| binding->dirty_check_frame == pg->frame_time) {
continue;
}
bool vram_dirty = check_texture_possibly_dirty(
d, binding->key.texture_vram_offset, binding->key.texture_length,
binding->key.palette_vram_offset, binding->key.palette_length);
binding->dirty_check_frame = pg->frame_time;
binding->dirty_check_result = vram_dirty;
if (!vram_dirty) {
binding->possibly_dirty = false;
}
}
for (int i = 0; i < NV2A_MAX_TEXTURES; i++) {
if (!pgraph_is_texture_enabled(pg, i)) {
r->texture_bindings[i] = &r->dummy_texture;
@@ -1452,6 +1490,9 @@ static void texture_cache_entry_init(Lru *lru, LruNode *node, const void *state)
snode->allocation = VK_NULL_HANDLE;
snode->image_view = VK_NULL_HANDLE;
snode->sampler = VK_NULL_HANDLE;
snode->submit_time = 0;
snode->dirty_check_frame = 0;
snode->dirty_check_result = false;
}
static void texture_cache_release_node_resources(PGRAPHVkState *r, TextureBinding *snode)