Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 14 additions & 21 deletions hw/xbox/nv2a/pgraph/gl/blit.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ static void perform_blit(int operation, uint8_t *source, uint8_t *dest,
}
} else {
fprintf(stderr, "Unknown blit operation: 0x%x\n", operation);
assert(false && "Unknown blit operation");
assert(!"Unknown blit operation");
}
}

Expand Down Expand Up @@ -115,15 +115,13 @@ void pgraph_gl_image_blit(NV2AState *d)
dest += context_surfaces->dest_offset;
hwaddr dest_addr = dest - d->vram_ptr;

SurfaceBinding *surf_src = pgraph_gl_surface_get(d, source_addr);
if (surf_src) {
pgraph_gl_surface_download_if_dirty(d, surf_src);
}

hwaddr source_offset = image_blit->in_y * context_surfaces->source_pitch +
image_blit->in_x * bytes_per_pixel;
source_addr += source_offset;

hwaddr dest_offset = image_blit->out_y * context_surfaces->dest_pitch +
image_blit->out_x * bytes_per_pixel;
dest_addr += dest_offset;

size_t max_row_pixels =
MIN(context_surfaces->source_pitch, context_surfaces->dest_pitch) /
Expand All @@ -150,20 +148,12 @@ void pgraph_gl_image_blit(NV2AState *d)
leftover_bytes = clipped_dest_size - consumed_bytes;
}

SurfaceBinding *surf_dest = pgraph_gl_surface_get(d, dest_addr);
if (surf_dest) {
if (adjusted_height < surf_dest->height ||
row_pixels < surf_dest->width) {
pgraph_gl_surface_download_if_dirty(d, surf_dest);
} else {
// The blit will completely replace the surface so any pending
// download should be discarded.
surf_dest->download_pending = false;
surf_dest->draw_dirty = false;
}
surf_dest->upload_pending = true;
pg->draw_time++;
}
hwaddr source_size = adjusted_height * context_surfaces->source_pitch +
image_blit->width * bytes_per_pixel;
pgraph_gl_download_surfaces_in_range_if_dirty(pg, source_addr, source_size);

// TODO: just clear dirty_draw flag on surfaces that are fully overlapped.
pgraph_gl_download_surfaces_in_range_if_dirty(pg, dest_addr, clipped_dest_size);

NV2A_DPRINTF(" blit 0x%tx -> 0x%tx (Size: %llu, Clipped Height: %zu)\n",
source_addr, dest_addr, dest_size, adjusted_height);
Expand Down Expand Up @@ -215,9 +205,12 @@ void pgraph_gl_image_blit(NV2AState *d)
}
}

dest_addr += dest_offset;
memory_region_set_client_dirty(d->vram, dest_addr, clipped_dest_size,
DIRTY_MEMORY_VGA);
memory_region_set_client_dirty(d->vram, dest_addr, clipped_dest_size,
DIRTY_MEMORY_NV2A_TEX);

if (pgraph_gl_mark_surfaces_in_range_for_upload(d, dest_addr, dest_size)) {
++pg->draw_time;
}
}
5 changes: 5 additions & 0 deletions hw/xbox/nv2a/pgraph/gl/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,11 @@ SurfaceBinding *pgraph_gl_surface_get(NV2AState *d, hwaddr addr);
SurfaceBinding *pgraph_gl_surface_get_within(NV2AState *d, hwaddr addr);
void pgraph_gl_surface_invalidate(NV2AState *d, SurfaceBinding *e);
void pgraph_gl_unbind_surface(NV2AState *d, bool color);
unsigned int pgraph_gl_mark_surfaces_in_range_for_upload(NV2AState *d,
hwaddr start,
hwaddr size);
void pgraph_gl_download_surfaces_in_range_if_dirty(PGRAPHState *pg,
hwaddr start, hwaddr size);
void pgraph_gl_upload_surface_data(NV2AState *d, SurfaceBinding *surface, bool force);
void pgraph_gl_shader_cache_to_disk(ShaderBinding *snode);
bool pgraph_gl_shader_load_from_memory(ShaderBinding *snode);
Expand Down
44 changes: 44 additions & 0 deletions hw/xbox/nv2a/pgraph/gl/surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,50 @@ void pgraph_gl_surface_download_if_dirty(NV2AState *d,
}
}

unsigned int pgraph_gl_mark_surfaces_in_range_for_upload(NV2AState *d,
hwaddr start,
hwaddr size)
{
PGRAPHState *pg = &d->pgraph;
PGRAPHGLState *r = pg->gl_renderer_state;

SurfaceBinding *surface;

hwaddr end = start + size - 1;

unsigned int num_marked = 0;
QTAILQ_FOREACH (surface, &r->surfaces, entry) {
hwaddr surf_end = surface->vram_addr + surface->size - 1;
bool overlapping = !(surface->vram_addr >= end || start >= surf_end);
if (overlapping) {
surface->upload_pending = true;
++num_marked;
}
}

return num_marked;
}


void pgraph_gl_download_surfaces_in_range_if_dirty(PGRAPHState *pg,
hwaddr start, hwaddr size)
{
PGRAPHGLState *r = pg->gl_renderer_state;

SurfaceBinding *surface;

hwaddr end = start + size - 1;

QTAILQ_FOREACH (surface, &r->surfaces, entry) {
hwaddr surf_end = surface->vram_addr + surface->size - 1;
bool overlapping = !(surface->vram_addr >= end || start >= surf_end);
if (overlapping) {
pgraph_gl_surface_download_if_dirty(
container_of(pg, NV2AState, pgraph), surface);
}
}
}

static void bind_current_surface(NV2AState *d)
{
PGRAPHState *pg = &d->pgraph;
Expand Down
35 changes: 14 additions & 21 deletions hw/xbox/nv2a/pgraph/vk/blit.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static void perform_blit(int operation, uint8_t *source, uint8_t *dest,
}
} else {
fprintf(stderr, "Unknown blit operation: 0x%x\n", operation);
assert(false && "Unknown blit operation");
assert(!"Unknown blit operation");
}
}

Expand Down Expand Up @@ -119,15 +119,13 @@ void pgraph_vk_image_blit(NV2AState *d)
dest += context_surfaces->dest_offset;
hwaddr dest_addr = dest - d->vram_ptr;

SurfaceBinding *surf_src = pgraph_vk_surface_get(d, source_addr);
if (surf_src) {
pgraph_vk_surface_download_if_dirty(d, surf_src);
}

hwaddr source_offset = image_blit->in_y * context_surfaces->source_pitch +
image_blit->in_x * bytes_per_pixel;
source_addr += source_offset;

hwaddr dest_offset = image_blit->out_y * context_surfaces->dest_pitch +
image_blit->out_x * bytes_per_pixel;
dest_addr += dest_offset;

size_t max_row_pixels =
MIN(context_surfaces->source_pitch, context_surfaces->dest_pitch) /
Expand All @@ -154,20 +152,12 @@ void pgraph_vk_image_blit(NV2AState *d)
leftover_bytes = clipped_dest_size - consumed_bytes;
}

SurfaceBinding *surf_dest = pgraph_vk_surface_get(d, dest_addr);
if (surf_dest) {
if (adjusted_height < surf_dest->height ||
row_pixels < surf_dest->width) {
pgraph_vk_surface_download_if_dirty(d, surf_dest);
} else {
// The blit will completely replace the surface so any pending
// download should be discarded.
surf_dest->download_pending = false;
surf_dest->draw_dirty = false;
}
surf_dest->upload_pending = true;
pg->draw_time++;
}
hwaddr source_size = adjusted_height * context_surfaces->source_pitch +
image_blit->width * bytes_per_pixel;
pgraph_vk_download_surfaces_in_range_if_dirty(pg, source_addr, source_size);

// TODO: just clear dirty_draw flag on surfaces that are fully overlapped.
pgraph_vk_download_surfaces_in_range_if_dirty(pg, dest_addr, clipped_dest_size);

NV2A_DPRINTF(" blit 0x%tx -> 0x%tx (Size: %llu, Clipped Height: %zu)\n",
source_addr, dest_addr, dest_size, adjusted_height);
Expand Down Expand Up @@ -219,9 +209,12 @@ void pgraph_vk_image_blit(NV2AState *d)
}
}

dest_addr += dest_offset;
memory_region_set_client_dirty(d->vram, dest_addr, clipped_dest_size,
DIRTY_MEMORY_VGA);
memory_region_set_client_dirty(d->vram, dest_addr, clipped_dest_size,
DIRTY_MEMORY_NV2A_TEX);

if (pgraph_vk_mark_surfaces_in_range_for_upload(d, dest_addr, dest_size)) {
++pg->draw_time;
}
}
3 changes: 3 additions & 0 deletions hw/xbox/nv2a/pgraph/vk/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,9 @@ void pgraph_vk_surface_download_if_dirty(NV2AState *d, SurfaceBinding *surface);
SurfaceBinding *pgraph_vk_surface_get_within(NV2AState *d, hwaddr addr);
void pgraph_vk_wait_for_surface_download(SurfaceBinding *e);
void pgraph_vk_download_dirty_surfaces(NV2AState *d);
unsigned int pgraph_vk_mark_surfaces_in_range_for_upload(NV2AState *d,
hwaddr start,
hwaddr size);
void pgraph_vk_download_surfaces_in_range_if_dirty(PGRAPHState *pg, hwaddr start, hwaddr size);
void pgraph_vk_upload_surface_data(NV2AState *d, SurfaceBinding *surface,
bool force);
Expand Down
23 changes: 23 additions & 0 deletions hw/xbox/nv2a/pgraph/vk/surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,29 @@ static void memcpy_image(void *dst, void const *src, int dst_stride,
}
}

unsigned int pgraph_vk_mark_surfaces_in_range_for_upload(NV2AState *d,
hwaddr start,
hwaddr size)
{
PGRAPHState *pg = &d->pgraph;
PGRAPHVkState *r = pg->vk_renderer_state;
SurfaceBinding *surface;

hwaddr end = start + size - 1;

unsigned int num_marked = 0;
QTAILQ_FOREACH (surface, &r->surfaces, entry) {
hwaddr surf_end = surface->vram_addr + surface->size - 1;
bool overlapping = !(surface->vram_addr >= end || start >= surf_end);
if (overlapping) {
surface->upload_pending = true;
++num_marked;
}
}

return num_marked;
}

static bool check_surface_overlaps_range(const SurfaceBinding *surface,
hwaddr range_start, hwaddr range_len)
{
Expand Down