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