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
3 changes: 3 additions & 0 deletions config_spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ display:
surface_scale:
type: integer
default: 1
anisotropic_filter_level:
type: integer
default: 1
window:
fullscreen_on_startup: bool
fullscreen_exclusive: bool
Expand Down
2 changes: 2 additions & 0 deletions hw/xbox/nv2a/nv2a.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ int nv2a_get_framebuffer_surface(void);
void nv2a_release_framebuffer_surface(void);
void nv2a_set_surface_scale_factor(unsigned int scale);
unsigned int nv2a_get_surface_scale_factor(void);
void nv2a_set_anisotropic_filter_level(unsigned int level_po2);
unsigned int nv2a_get_anisotropic_filter_level(void);
const uint8_t *nv2a_get_dac_palette(void);
int nv2a_get_screen_off(void);

Expand Down
2 changes: 2 additions & 0 deletions hw/xbox/nv2a/pgraph/gl/renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ static PGRAPHRenderer pgraph_gl_renderer = {
.surface_update = pgraph_gl_surface_update,
.set_surface_scale_factor = pgraph_gl_set_surface_scale_factor,
.get_surface_scale_factor = pgraph_gl_get_surface_scale_factor,
.set_anisotropic_filter_level = pgraph_gl_set_anisotropic_filter_level,
.get_anisotropic_filter_level = pgraph_gl_get_anisotropic_filter_level,
.get_framebuffer_surface = pgraph_gl_get_framebuffer_surface,
}
};
Expand Down
3 changes: 3 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,9 @@ bool pgraph_gl_shader_load_from_memory(ShaderBinding *snode);
void pgraph_gl_shader_write_cache_reload_list(PGRAPHState *pg);
void pgraph_gl_set_surface_scale_factor(NV2AState *d, unsigned int scale);
unsigned int pgraph_gl_get_surface_scale_factor(NV2AState *d);
void pgraph_gl_set_anisotropic_filter_level(NV2AState *d, unsigned int level_po2);
unsigned int pgraph_gl_get_anisotropic_filter_level(NV2AState *d);
void pgraph_gl_reload_anisotropic_filter_level(PGRAPHState *pg);
int pgraph_gl_get_framebuffer_surface(NV2AState *d);

#endif
53 changes: 53 additions & 0 deletions hw/xbox/nv2a/pgraph/gl/texture.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "hw/xbox/nv2a/pgraph/swizzle.h"
#include "hw/xbox/nv2a/pgraph/s3tc.h"
#include "hw/xbox/nv2a/pgraph/texture.h"
#include "ui/xemu-settings.h"
#include "debug.h"
#include "renderer.h"

Expand Down Expand Up @@ -112,6 +113,7 @@ static void apply_texture_parameters(TextureBinding *binding,
unsigned int dimensionality,
unsigned int filter,
unsigned int address,
unsigned int anisotropic_filter_level,
bool is_bordered,
uint32_t border_color)
{
Expand Down Expand Up @@ -174,6 +176,8 @@ static void apply_texture_parameters(TextureBinding *binding,
needs_border_color = needs_border_color || binding->addrp == NV_PGRAPH_TEXADDRESS0_ADDRU_BORDER;
}

glTexParameterf(binding->gl_target, GL_TEXTURE_MAX_ANISOTROPY, 1 << anisotropic_filter_level);

if (!is_bordered && needs_border_color) {
if (!binding->border_color_set || binding->border_color != border_color) {
/* FIXME: Color channels might be wrong order */
Expand Down Expand Up @@ -260,6 +264,7 @@ void pgraph_gl_bind_textures(NV2AState *d)
state.dimensionality,
filter,
address,
pg->anisotropic_filter_level,
state.border,
border_color);
continue;
Expand Down Expand Up @@ -370,6 +375,7 @@ void pgraph_gl_bind_textures(NV2AState *d)
state.dimensionality,
filter,
address,
pg->anisotropic_filter_level,
state.border,
border_color);

Expand Down Expand Up @@ -771,6 +777,53 @@ static bool texture_cache_entry_compare(Lru *lru, LruNode *node, void *key)
return memcmp(&tnode->key, key, sizeof(TextureKey));
}

void pgraph_gl_set_anisotropic_filter_level(NV2AState *d, unsigned int level_po2)
{
PGRAPHState *pg = &d->pgraph;
PGRAPHGLState *r = pg->gl_renderer_state;

g_config.display.quality.anisotropic_filter_level = level_po2;

qemu_mutex_lock(&d->pfifo.lock);
qatomic_set(&d->pfifo.halt, true);
qemu_mutex_unlock(&d->pfifo.lock);

qemu_mutex_lock(&d->pgraph.lock);
qemu_event_reset(&r->dirty_surfaces_download_complete);
qatomic_set(&r->download_dirty_surfaces_pending, true);
qemu_mutex_unlock(&d->pgraph.lock);
qemu_mutex_lock(&d->pfifo.lock);
pfifo_kick(d);
qemu_mutex_unlock(&d->pfifo.lock);
qemu_event_wait(&r->dirty_surfaces_download_complete);

qemu_mutex_lock(&d->pgraph.lock);
qemu_event_reset(&d->pgraph.flush_complete);
qatomic_set(&d->pgraph.flush_pending, true);
qemu_mutex_unlock(&d->pgraph.lock);
qemu_mutex_lock(&d->pfifo.lock);
pfifo_kick(d);
qemu_mutex_unlock(&d->pfifo.lock);
qemu_event_wait(&d->pgraph.flush_complete);

qemu_mutex_lock(&d->pfifo.lock);
qatomic_set(&d->pfifo.halt, false);
pfifo_kick(d);
qemu_mutex_unlock(&d->pfifo.lock);

pgraph_gl_reload_anisotropic_filter_level(&d->pgraph);
}

unsigned int pgraph_gl_get_anisotropic_filter_level(NV2AState *d)
{
return d->pgraph.anisotropic_filter_level;
}

void pgraph_gl_reload_anisotropic_filter_level(PGRAPHState *pg)
{
pg->anisotropic_filter_level = g_config.display.quality.anisotropic_filter_level;
}

void pgraph_gl_init_textures(NV2AState *d)
{
PGRAPHState *pg = &d->pgraph;
Expand Down
30 changes: 29 additions & 1 deletion hw/xbox/nv2a/pgraph/pgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,35 @@ unsigned int nv2a_get_surface_scale_factor(void)
return s;
}

void nv2a_set_anisotropic_filter_level(unsigned int level_po2)
{
NV2AState *d = g_nv2a;

bql_unlock();
qemu_mutex_lock(&d->pgraph.renderer_lock);
if (d->pgraph.renderer->ops.set_anisotropic_filter_level) {
d->pgraph.renderer->ops.set_anisotropic_filter_level(d, level_po2);
}
qemu_mutex_unlock(&d->pgraph.renderer_lock);
bql_lock();
}

unsigned int nv2a_get_anisotropic_filter_level(void)
{
NV2AState *d = g_nv2a;
int s = 1;

bql_unlock();
qemu_mutex_lock(&d->pgraph.renderer_lock);
if (d->pgraph.renderer->ops.get_anisotropic_filter_level) {
s = d->pgraph.renderer->ops.get_anisotropic_filter_level(d);
}
qemu_mutex_unlock(&d->pgraph.renderer_lock);
bql_lock();

return s;
}

#define METHOD_ADDR(gclass, name) \
gclass ## _ ## name
#define METHOD_ADDR_TO_INDEX(x) ((x)>>2)
Expand Down Expand Up @@ -3022,4 +3051,3 @@ void pgraph_pre_shutdown_wait(NV2AState *d)
PGRAPHState *pg = &d->pgraph;
pg->renderer->ops.pre_shutdown_wait(d);
}

5 changes: 5 additions & 0 deletions hw/xbox/nv2a/pgraph/pgraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ typedef struct PGRAPHRenderer {
void (*surface_update)(NV2AState *d, bool upload, bool color_write, bool zeta_write);
void (*set_surface_scale_factor)(NV2AState *d, unsigned int scale);
unsigned int (*get_surface_scale_factor)(NV2AState *d);
void (*set_anisotropic_filter_level)(NV2AState *d, unsigned int level_po2);
unsigned int (*get_anisotropic_filter_level)(NV2AState *d);
int (*get_framebuffer_surface)(NV2AState *d);
} ops;
} PGRAPHRenderer;
Expand Down Expand Up @@ -241,6 +243,9 @@ typedef struct PGRAPHState {
unsigned int surface_scale_factor;
uint8_t *scale_buf;

// Defined as a power of 2
unsigned int anisotropic_filter_level;

const PGRAPHRenderer *renderer;
union {
PGRAPHNullState *null_renderer_state;
Expand Down
4 changes: 3 additions & 1 deletion hw/xbox/nv2a/pgraph/vk/renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ static void pgraph_vk_pre_shutdown_trigger(NV2AState *d)

static void pgraph_vk_pre_shutdown_wait(NV2AState *d)
{
// qemu_event_wait(&d->pgraph.vk_renderer_state->shader_cache_writeback_complete);
// qemu_event_wait(&d->pgraph.vk_renderer_state->shader_cache_writeback_complete);
}

static int pgraph_vk_get_framebuffer_surface(NV2AState *d)
Expand Down Expand Up @@ -226,6 +226,8 @@ static PGRAPHRenderer pgraph_vk_renderer = {
.surface_update = pgraph_vk_surface_update,
.set_surface_scale_factor = pgraph_vk_set_surface_scale_factor,
.get_surface_scale_factor = pgraph_vk_get_surface_scale_factor,
.set_anisotropic_filter_level = pgraph_vk_set_anisotropic_filter_level,
.get_anisotropic_filter_level = pgraph_vk_get_anisotropic_filter_level,
.get_framebuffer_surface = pgraph_vk_get_framebuffer_surface,
}
};
Expand Down
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 @@ -544,6 +544,9 @@ void pgraph_vk_bind_textures(NV2AState *d);
void pgraph_vk_mark_textures_possibly_dirty(NV2AState *d, hwaddr addr,
hwaddr size);
void pgraph_vk_trim_texture_cache(PGRAPHState *pg);
void pgraph_vk_set_anisotropic_filter_level(NV2AState *d, unsigned int level_po2);
unsigned int pgraph_vk_get_anisotropic_filter_level(NV2AState *d);
void pgraph_vk_reload_anisotropic_filter_level(PGRAPHState *pg);

// shaders.c
void pgraph_vk_init_shaders(PGRAPHState *pg);
Expand Down
50 changes: 47 additions & 3 deletions hw/xbox/nv2a/pgraph/vk/texture.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "hw/xbox/nv2a/pgraph/swizzle.h"
#include "qemu/fast-hash.h"
#include "qemu/lru.h"
#include "ui/xemu-settings.h"
#include "renderer.h"

static void texture_cache_release_node_resources(PGRAPHVkState *r, TextureBinding *snode);
Expand Down Expand Up @@ -1345,9 +1346,8 @@ static void create_texture(PGRAPHState *pg, int texture_idx)
GET_MASK(address, NV_PGRAPH_TEXADDRESS0_ADDRV)),
.addressModeW = lookup_texture_address_mode(
GET_MASK(address, NV_PGRAPH_TEXADDRESS0_ADDRP)),
.anisotropyEnable = VK_FALSE,
// .anisotropyEnable = VK_TRUE,
// .maxAnisotropy = properties.limits.maxSamplerAnisotropy,
.anisotropyEnable = pg->anisotropic_filter_level >= 1,
.maxAnisotropy = 1 << pg->anisotropic_filter_level,
.borderColor = vk_border_color,
.compareEnable = VK_FALSE,
.compareOp = VK_COMPARE_OP_ALWAYS,
Expand Down Expand Up @@ -1529,6 +1529,50 @@ void pgraph_vk_trim_texture_cache(PGRAPHState *pg)
NV2A_VK_DPRINTF("Evicted %d textures, %d remain", num_evicted, r->texture_cache.num_used);
}

void pgraph_vk_set_anisotropic_filter_level(NV2AState *d, unsigned int level_po2)
{
g_config.display.quality.anisotropic_filter_level = level_po2;

qemu_mutex_lock(&d->pfifo.lock);
qatomic_set(&d->pfifo.halt, true);
qemu_mutex_unlock(&d->pfifo.lock);

qemu_mutex_lock(&d->pgraph.lock);
qemu_event_reset(&d->pgraph.vk_renderer_state->dirty_surfaces_download_complete);
qatomic_set(&d->pgraph.vk_renderer_state->download_dirty_surfaces_pending, true);
qemu_mutex_unlock(&d->pgraph.lock);
qemu_mutex_lock(&d->pfifo.lock);
pfifo_kick(d);
qemu_mutex_unlock(&d->pfifo.lock);
qemu_event_wait(&d->pgraph.vk_renderer_state->dirty_surfaces_download_complete);

qemu_mutex_lock(&d->pgraph.lock);
qemu_event_reset(&d->pgraph.flush_complete);
qatomic_set(&d->pgraph.flush_pending, true);
qemu_mutex_unlock(&d->pgraph.lock);
qemu_mutex_lock(&d->pfifo.lock);
pfifo_kick(d);
qemu_mutex_unlock(&d->pfifo.lock);
qemu_event_wait(&d->pgraph.flush_complete);

qemu_mutex_lock(&d->pfifo.lock);
qatomic_set(&d->pfifo.halt, false);
pfifo_kick(d);
qemu_mutex_unlock(&d->pfifo.lock);

pgraph_vk_reload_anisotropic_filter_level(&d->pgraph);
}

unsigned int pgraph_vk_get_anisotropic_filter_level(NV2AState *d)
{
return d->pgraph.anisotropic_filter_level;
}

void pgraph_vk_reload_anisotropic_filter_level(PGRAPHState *pg)
{
pg->anisotropic_filter_level = g_config.display.quality.anisotropic_filter_level;
}

void pgraph_vk_init_textures(PGRAPHState *pg)
{
PGRAPHVkState *r = pg->vk_renderer_state;
Expand Down
21 changes: 16 additions & 5 deletions ui/xui/main-menu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -172,14 +172,14 @@ void MainMenuInputView::Draw()
driver = DRIVER_DUKE_DISPLAY_NAME;
else if (strcmp(driver, DRIVER_S) == 0)
driver = DRIVER_S_DISPLAY_NAME;

ImGui::SetNextItemWidth(-FLT_MIN);
if (ImGui::BeginCombo("###InputDrivers", driver,
ImGuiComboFlags_NoArrowButton)) {
const char *available_drivers[] = { DRIVER_DUKE, DRIVER_S };
const char *driver_display_names[] = {
DRIVER_DUKE_DISPLAY_NAME,
DRIVER_S_DISPLAY_NAME
const char *driver_display_names[] = {
DRIVER_DUKE_DISPLAY_NAME,
DRIVER_S_DISPLAY_NAME
};
bool is_selected = false;
int num_drivers = sizeof(driver_display_names) / sizeof(driver_display_names[0]);
Expand Down Expand Up @@ -513,10 +513,21 @@ void MainMenuDisplayView::Draw()
"8x\0"
"9x\0"
"10x\0",
"Increase surface scaling factor for higher quality")) {
"Increase surface scaling factor for higher overall quality")) {
nv2a_set_surface_scale_factor(rendering_scale+1);
}

int anisotropic_filter_level = nv2a_get_anisotropic_filter_level();
if (ChevronCombo("Anisotropic filtering level", &anisotropic_filter_level,
"Disabled\0"
"2x\0"
"4x\0"
"8x\0"
"16x\0",
"Increase anisotropic filtering level for sharper textures at oblique angles")) {
nv2a_set_anisotropic_filter_level(anisotropic_filter_level);
}

SectionTitle("Window");
bool fs = xemu_is_fullscreen();
if (Toggle("Fullscreen", &fs, "Enable fullscreen now")) {
Expand Down
10 changes: 10 additions & 0 deletions ui/xui/menubar.cc
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,16 @@ void ShowMainMenu()
nv2a_set_surface_scale_factor(rendering_scale + 1);
}

int anisotropic_filter_level = nv2a_get_anisotropic_filter_level();
if (ImGui::Combo("Anisotropic Filtering Level", &anisotropic_filter_level,
"Disabled\0"
"2x\0"
"4x\0"
"8x\0"
"16x\0")) {
nv2a_set_anisotropic_filter_level(anisotropic_filter_level);
}

ImGui::Combo("Display Mode", &g_config.display.ui.fit,
"Center\0Scale\0Stretch\0");
ImGui::SameLine();
Expand Down