mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Port hakuX Vulkan texture dirty-check fast path
This commit is contained in:
@@ -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++;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user