Port hakuX Phase 1 super fast path foundation

This commit is contained in:
izzy2lost
2026-04-08 02:34:56 -04:00
parent e72dc18125
commit ad2aa65503
3 changed files with 81 additions and 16 deletions
+56 -16
View File
@@ -764,17 +764,8 @@ static bool check_pipeline_dirty(PGRAPHState *pg)
r->texture_bindings_changed || check_render_pass_dirty(pg)) {
return true;
}
const unsigned int regs[] = {
NV_PGRAPH_BLEND, NV_PGRAPH_BLENDCOLOR, NV_PGRAPH_CONTROL_0,
NV_PGRAPH_CONTROL_1, NV_PGRAPH_CONTROL_2, NV_PGRAPH_CONTROL_3,
NV_PGRAPH_SETUPRASTER, NV_PGRAPH_ZOFFSETBIAS, NV_PGRAPH_ZOFFSETFACTOR,
};
for (int i = 0; i < ARRAY_SIZE(regs); i++) {
if (pgraph_is_reg_dirty(pg, regs[i])) {
return true;
}
if (pg->pipeline_state_gen != r->last_pipeline_state_gen) {
return true;
}
// FIXME: Use dirty bits instead
@@ -827,16 +818,31 @@ static void create_pipeline(PGRAPHState *pg)
NV2AState *d = container_of(pg, NV2AState, pgraph);
PGRAPHVkState *r = pg->vk_renderer_state;
bool textures_clean = pgraph_vk_check_textures_fast_skip(pg);
pgraph_vk_bind_textures(d);
if (r->pipeline_binding &&
pg->texture_state_gen == r->last_texture_state_gen &&
textures_clean &&
!check_render_pass_dirty(pg) &&
pg->shader_state_gen == r->last_shader_state_gen &&
pg->pipeline_state_gen == r->last_pipeline_state_gen &&
pg->primitive_mode == r->shader_binding->state.geom.primitive_mode) {
NV2A_VK_DGROUP_END();
return;
}
if (pg->texture_state_gen != r->last_texture_state_gen || !textures_clean) {
pgraph_vk_bind_textures(d);
r->last_texture_state_gen = pg->texture_state_gen;
}
pgraph_vk_bind_shaders(pg);
// FIXME: If nothing was dirty, don't even try creating the key or hashing.
// Just use the same pipeline.
bool pipeline_dirty = check_pipeline_dirty(pg);
pgraph_clear_dirty_reg_map(pg);
// FIXME: We could clear less
r->last_pipeline_state_gen = pg->pipeline_state_gen;
r->last_shader_state_gen = pg->shader_state_gen;
r->last_any_reg_gen = pg->any_reg_gen;
if (r->pipeline_binding && !pipeline_dirty) {
NV2A_VK_DPRINTF("Cache hit");
@@ -1531,15 +1537,42 @@ void pgraph_vk_end_nondraw_commands(PGRAPHState *pg, VkCommandBuffer cmd)
static void begin_pre_draw(PGRAPHState *pg)
{
PGRAPHVkState *r = pg->vk_renderer_state;
bool textures_clean = pgraph_vk_check_textures_fast_skip(pg);
assert(r->color_binding || r->zeta_binding);
assert(!r->color_binding || r->color_binding->initialized);
assert(!r->zeta_binding || r->zeta_binding->initialized);
if (!pg->clearing &&
r->pipeline_binding &&
r->shader_binding &&
r->pipeline_binding->pipeline != VK_NULL_HANDLE &&
!r->pipeline_binding_changed &&
r->in_command_buffer &&
r->in_render_pass &&
r->framebuffer_index > 0 &&
!r->framebuffer_dirty &&
!r->uniforms_changed &&
r->descriptor_set_index > 0 &&
pg->texture_state_gen == r->last_texture_state_gen &&
textures_clean &&
pg->shader_state_gen == r->last_shader_state_gen &&
pg->pipeline_state_gen == r->last_pipeline_state_gen &&
pg->any_reg_gen == r->last_any_reg_gen &&
pg->primitive_mode == r->shader_binding->state.geom.primitive_mode &&
!pg->program_data_dirty &&
pg->vertex_attr_gen == r->pipeline_vertex_attr_gen) {
r->pre_draw_skipped = true;
return;
}
r->pre_draw_skipped = false;
if (pg->clearing) {
create_clear_pipeline(pg);
} else {
create_pipeline(pg);
r->pipeline_vertex_attr_gen = pg->vertex_attr_gen;
}
bool render_pass_dirty = r->pipeline_binding->render_pass != r->render_pass;
@@ -1556,12 +1589,18 @@ static void begin_pre_draw(PGRAPHState *pg)
}
if (!pg->clearing) {
pgraph_vk_update_descriptor_sets(pg);
r->shader_bindings_changed = false;
r->texture_bindings_changed = false;
}
if (r->framebuffer_index == 0) {
create_frame_buffer(pg);
}
pgraph_vk_ensure_command_buffer(pg);
pgraph_clear_dirty_reg_map(pg);
r->last_any_reg_gen = pg->any_reg_gen;
r->last_shader_state_gen = pg->shader_state_gen;
r->last_pipeline_state_gen = pg->pipeline_state_gen;
}
static float clamp_line_width_to_device_limits(PGRAPHState *pg, float width)
@@ -1615,6 +1654,7 @@ static void begin_draw(PGRAPHState *pg)
nv2a_profile_inc_counter(NV2A_PROF_PIPELINE_BIND);
vkCmdBindPipeline(r->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
r->pipeline_binding->pipeline);
r->pipeline_binding_changed = false;
r->pipeline_binding->draw_time = pg->draw_time;
unsigned int vp_width = pg->surface_binding_dim.width,
@@ -1658,7 +1698,7 @@ static void begin_draw(PGRAPHState *pg)
}
}
if (!pg->clearing) {
if (!pg->clearing && !r->pre_draw_skipped) {
bind_descriptor_sets(pg);
push_vertex_attr_values(pg);
}
+7
View File
@@ -427,6 +427,10 @@ typedef struct PGRAPHVkState {
size_t num_vertex_ram_buffer_syncs;
unsigned long *uploaded_bitmap;
size_t bitmap_size;
uint32_t pipeline_vertex_attr_gen;
uint32_t last_shader_state_gen;
uint32_t last_pipeline_state_gen;
uint32_t last_any_reg_gen;
VkVertexInputAttributeDescription vertex_attribute_descriptions[NV2A_VERTEXSHADER_ATTRIBUTES];
int vertex_attribute_to_description_location[NV2A_VERTEXSHADER_ATTRIBUTES];
@@ -454,6 +458,7 @@ typedef struct PGRAPHVkState {
VkImageView tex_surface_direct_views[NV2A_MAX_TEXTURES];
VkImageLayout tex_surface_direct_layout[NV2A_MAX_TEXTURES];
TextureBinding dummy_texture;
uint32_t last_texture_state_gen;
bool texture_bindings_changed;
VkFormatProperties *texture_format_properties;
@@ -472,6 +477,7 @@ typedef struct PGRAPHVkState {
uint64_t uniform_buffer_hashes[2];
size_t uniform_buffer_offsets[2];
bool uniforms_changed;
bool pre_draw_skipped;
VkQueryPool query_pool;
int max_queries_in_flight; // FIXME: Move out to constant
@@ -618,6 +624,7 @@ bool pgraph_vk_gl_external_memory_available(void);
void pgraph_vk_init_textures(PGRAPHState *pg);
void pgraph_vk_finalize_textures(PGRAPHState *pg);
void pgraph_vk_bind_textures(NV2AState *d);
bool pgraph_vk_check_textures_fast_skip(PGRAPHState *pg);
void pgraph_vk_mark_textures_possibly_dirty(NV2AState *d, hwaddr addr,
hwaddr size);
void pgraph_vk_trim_texture_cache(PGRAPHState *pg);
+18
View File
@@ -1898,6 +1898,24 @@ static bool check_textures_dirty(PGRAPHState *pg)
return false;
}
bool pgraph_vk_check_textures_fast_skip(PGRAPHState *pg)
{
PGRAPHVkState *r = pg->vk_renderer_state;
for (int i = 0; i < NV2A_MAX_TEXTURES; i++) {
if (!r->texture_bindings[i] || pg->texture_dirty[i] ||
r->tex_surface_direct[i]) {
return false;
}
if (r->texture_bindings[i] != &r->dummy_texture &&
r->texture_bindings[i]->possibly_dirty) {
return false;
}
}
return true;
}
static void update_timestamps(PGRAPHVkState *r)
{
for (int i = 0; i < ARRAY_SIZE(r->texture_bindings); i++) {