Merge branch 'master' into DeviceEmulation-SteelBattalionController

This commit is contained in:
Fred Hallock 2025-05-20 23:07:19 -04:00 committed by GitHub
commit 89f34dce27
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 114 additions and 126 deletions

View File

@ -44,7 +44,7 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push image
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v5
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v5
with:
context: ubuntu-win64-cross
push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}

View File

@ -17,7 +17,7 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Install the latest version of uv
uses: astral-sh/setup-uv@c7f87aa956e4c323abf06d5dec078e358f6b4d04 # v6
uses: astral-sh/setup-uv@6b9c6063abd6010835644d4c2e1bef4cf5cd0fca # v6
with:
enable-cache: false

View File

@ -54,6 +54,9 @@ input:
auto_bind:
type: bool
default: true
allow_vibration:
type: bool
default: true
background_input_capture: bool
keyboard_controller_scancode_map:
# Scancode reference : https://github.com/libsdl-org/SDL/blob/main/include/SDL_scancode.h

View File

@ -155,8 +155,9 @@ static inline void nv2a_profile_inc_counter(enum NV2A_PROF_COUNTERS_ENUM cnt)
void nv2a_dbg_renderdoc_init(void);
void *nv2a_dbg_renderdoc_get_api(void);
bool nv2a_dbg_renderdoc_available(void);
void nv2a_dbg_renderdoc_capture_frames(int num_frames);
void nv2a_dbg_renderdoc_capture_frames(int num_frames, bool trace);
extern int renderdoc_capture_frames;
extern bool renderdoc_trace_frames;
#endif
#ifdef __cplusplus

View File

@ -36,6 +36,7 @@
static RENDERDOC_API_1_6_0 *rdoc_api = NULL;
int renderdoc_capture_frames = 0;
bool renderdoc_trace_frames = false;
void nv2a_dbg_renderdoc_init(void)
{
@ -89,7 +90,8 @@ bool nv2a_dbg_renderdoc_available(void)
return rdoc_api != NULL;
}
void nv2a_dbg_renderdoc_capture_frames(int num_frames)
void nv2a_dbg_renderdoc_capture_frames(int num_frames, bool trace)
{
renderdoc_capture_frames += num_frames;
renderdoc_trace_frames = trace;
}

View File

@ -29,6 +29,8 @@
#include <assert.h>
#ifdef CONFIG_RENDERDOC
#include "trace/control.h"
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#include "thirdparty/renderdoc_app.h"
#endif
@ -154,7 +156,8 @@ void gl_debug_frame_terminator(void)
RENDERDOC_API_1_6_0 *rdoc_api = nv2a_dbg_renderdoc_get_api();
if (rdoc_api->IsTargetControlConnected()) {
if (rdoc_api->IsFrameCapturing()) {
bool capturing = rdoc_api->IsFrameCapturing();
if (capturing && renderdoc_capture_frames == 0) {
rdoc_api->EndFrameCapture(NULL, NULL);
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
@ -162,14 +165,23 @@ void gl_debug_frame_terminator(void)
"Renderdoc EndFrameCapture triggered GL error 0x%X - ignoring\n",
error);
}
if (renderdoc_trace_frames) {
trace_enable_events("-nv2a_pgraph_*");
renderdoc_trace_frames = false;
}
}
if (renderdoc_capture_frames > 0) {
rdoc_api->StartFrameCapture(NULL, NULL);
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
fprintf(stderr,
"Renderdoc StartFrameCapture triggered GL error 0x%X - ignoring\n",
error);
if (!capturing) {
if (renderdoc_trace_frames) {
trace_enable_events("nv2a_pgraph_*");
}
rdoc_api->StartFrameCapture(NULL, NULL);
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
fprintf(stderr,
"Renderdoc StartFrameCapture triggered GL error 0x%X - ignoring\n",
error);
}
}
--renderdoc_capture_frames;
}

View File

@ -68,7 +68,7 @@ void pgraph_gl_init_display(NV2AState *d)
"{\n"
" vec2 texCoord = gl_FragCoord.xy/display_size;\n"
" float rel = display_size.y/textureSize(tex, 0).y/line_offset;\n"
" texCoord.y = 1 + rel*(texCoord.y - 1);"
" texCoord.y = rel*(1.0f - texCoord.y);"
" out_Color.rgba = texture(tex, texCoord);\n"
" if (pvideo_enable) {\n"
" vec2 screenCoord = gl_FragCoord.xy - 0.5;\n"

View File

@ -92,7 +92,6 @@ void pgraph_gl_clear_surface(NV2AState *d, uint32_t parameter)
scissor_height = ymax - ymin + 1;
pgraph_apply_anti_aliasing_factor(pg, &xmin, &ymin);
pgraph_apply_anti_aliasing_factor(pg, &scissor_width, &scissor_height);
ymin = pg->surface_binding_dim.height - (ymin + scissor_height);
NV2A_DPRINTF("Translated clear rect to %d,%d - %d,%d\n", xmin, ymin,
xmin + scissor_width - 1, ymin + scissor_height - 1);
@ -204,9 +203,10 @@ void pgraph_gl_draw_begin(NV2AState *d)
}
/* Front-face select */
/* Winding is reverse here because clip-space y-coordinates are inverted */
glFrontFace(pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER)
& NV_PGRAPH_SETUPRASTER_FRONTFACE
? GL_CCW : GL_CW);
? GL_CW : GL_CCW);
/* Polygon offset */
/* FIXME: GL implementation-specific, maybe do this in VS? */
@ -340,7 +340,6 @@ void pgraph_gl_draw_begin(NV2AState *d)
pgraph_apply_anti_aliasing_factor(pg, &xmin, &ymin);
pgraph_apply_anti_aliasing_factor(pg, &scissor_width, &scissor_height);
ymin = pg->surface_binding_dim.height - (ymin + scissor_height);
pgraph_apply_scaling_factor(pg, &xmin, &ymin);
pgraph_apply_scaling_factor(pg, &scissor_width, &scissor_height);

View File

@ -111,7 +111,6 @@ typedef struct ShaderBinding {
GLint vsh_constant_loc[NV2A_VERTEXSHADER_CONSTANTS];
uint32_t vsh_constants[NV2A_VERTEXSHADER_CONSTANTS][4];
GLint inv_viewport_loc;
GLint ltctxa_loc[NV2A_LTCTXA_COUNT];
GLint ltctxb_loc[NV2A_LTCTXB_COUNT];
GLint ltc1_loc[NV2A_LTC1_COUNT];

View File

@ -158,7 +158,6 @@ static void update_shader_constant_locations(ShaderBinding *binding)
binding->fog_color_loc = glGetUniformLocation(binding->gl_program, "fogColor");
binding->fog_param_loc = glGetUniformLocation(binding->gl_program, "fogParam");
binding->inv_viewport_loc = glGetUniformLocation(binding->gl_program, "invViewport");
for (int i = 0; i < NV2A_LTCTXA_COUNT; i++) {
snprintf(tmp, sizeof(tmp), "ltctxa[%d]", i);
binding->ltctxa_loc[i] = glGetUniformLocation(binding->gl_program, tmp);
@ -847,28 +846,6 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding,
if (binding->specular_power_loc != -1) {
glUniform1f(binding->specular_power_loc, pg->specular_power);
}
/* estimate the viewport by assuming it matches the surface ... */
unsigned int aa_width = 1, aa_height = 1;
pgraph_apply_anti_aliasing_factor(pg, &aa_width, &aa_height);
float m11 = 0.5 * (pg->surface_binding_dim.width/aa_width);
float m22 = -0.5 * (pg->surface_binding_dim.height/aa_height);
float m33 = zmax;
float m41 = *(float*)&pg->vsh_constants[NV_IGRAPH_XF_XFCTX_VPOFF][0];
float m42 = *(float*)&pg->vsh_constants[NV_IGRAPH_XF_XFCTX_VPOFF][1];
float invViewport[16] = {
1.0/m11, 0, 0, 0,
0, 1.0/m22, 0, 0,
0, 0, 1.0/m33, 0,
-1.0+m41/m11, 1.0+m42/m22, 0, 1.0
};
if (binding->inv_viewport_loc != -1) {
glUniformMatrix4fv(binding->inv_viewport_loc,
1, GL_FALSE, &invViewport[0]);
}
}
/* update vertex program constants */
@ -947,12 +924,8 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding,
pgraph_apply_scaling_factor(pg, &x_min, &y_min);
pgraph_apply_scaling_factor(pg, &x_max, &y_max);
/* Translate for the GL viewport origin */
int y_min_xlat = MAX((int)max_gl_height - (int)y_max, 0);
int y_max_xlat = MIN((int)max_gl_height - (int)y_min, max_gl_height);
glUniform4i(r->shader_binding->clip_region_loc[i],
x_min, y_min_xlat, x_max, y_max_xlat);
x_min, y_min, x_max, y_max);
}
for (i = 0; i < 8; ++i) {

View File

@ -137,11 +137,7 @@ static void init_render_to_texture(PGRAPHState *pg)
"layout(location = 0) out vec4 out_Color;\n"
"void main()\n"
"{\n"
" vec2 texCoord;\n"
" texCoord.x = gl_FragCoord.x;\n"
" texCoord.y = (surface_size.y - gl_FragCoord.y)\n"
" + (textureSize(tex,0).y - surface_size.y);\n"
" texCoord /= textureSize(tex,0).xy;\n"
" vec2 texCoord = gl_FragCoord.xy / textureSize(tex, 0).xy;\n"
" out_Color.rgba = texture(tex, texCoord);\n"
"}\n";
@ -298,7 +294,7 @@ static void render_surface_to_texture_slow(NV2AState *d,
size_t bufsize = width * height * surface->fmt.bytes_per_pixel;
uint8_t *buf = g_malloc(bufsize);
surface_download_to_buffer(d, surface, false, true, false, buf);
surface_download_to_buffer(d, surface, false, false, false, buf);
width = texture_shape->width;
height = texture_shape->height;
@ -738,7 +734,7 @@ static void surface_download(NV2AState *d, SurfaceBinding *surface, bool force)
nv2a_profile_inc_counter(NV2A_PROF_SURF_DOWNLOAD);
surface_download_to_buffer(d, surface, true, true, true,
surface_download_to_buffer(d, surface, true, false, true,
d->vram_ptr + surface->vram_addr);
memory_region_set_client_dirty(d->vram, surface->vram_addr,
@ -875,20 +871,26 @@ void pgraph_gl_upload_surface_data(NV2AState *d, SurfaceBinding *surface,
surface->fmt.bytes_per_pixel);
}
/* FIXME: Replace this flip/scaling */
/* FIXME: Replace this scaling */
// This is VRAM so we can't do this inplace!
uint8_t *flipped_buf = (uint8_t *)g_malloc(
surface->height * surface->width * surface->fmt.bytes_per_pixel);
unsigned int irow;
for (irow = 0; irow < surface->height; irow++) {
memcpy(&flipped_buf[surface->width * (surface->height - irow - 1)
* surface->fmt.bytes_per_pixel],
&buf[surface->pitch * irow],
surface->width * surface->fmt.bytes_per_pixel);
uint8_t *optimal_buf = buf;
unsigned int optimal_pitch = surface->width * surface->fmt.bytes_per_pixel;
if (surface->pitch != optimal_pitch) {
optimal_buf = (uint8_t *)g_malloc(surface->height * optimal_pitch);
uint8_t *src = buf;
uint8_t *dst = optimal_buf;
unsigned int irow;
for (irow = 0; irow < surface->height; irow++) {
memcpy(dst, src, optimal_pitch);
src += surface->pitch;
dst += optimal_pitch;
}
}
uint8_t *gl_read_buf = flipped_buf;
uint8_t *gl_read_buf = optimal_buf;
unsigned int width = surface->width, height = surface->height;
if (pg->surface_scale_factor > 1) {
@ -896,7 +898,7 @@ void pgraph_gl_upload_surface_data(NV2AState *d, SurfaceBinding *surface,
pg->scale_buf = (uint8_t *)g_realloc(
pg->scale_buf, width * height * surface->fmt.bytes_per_pixel);
gl_read_buf = pg->scale_buf;
uint8_t *out = gl_read_buf, *in = flipped_buf;
uint8_t *out = gl_read_buf, *in = optimal_buf;
surface_copy_expand(out, in, surface->width, surface->height,
surface->fmt.bytes_per_pixel,
d->pgraph.surface_scale_factor);
@ -915,7 +917,9 @@ void pgraph_gl_upload_surface_data(NV2AState *d, SurfaceBinding *surface,
height, 0, surface->fmt.gl_format, surface->fmt.gl_type,
gl_read_buf);
glPixelStorei(GL_UNPACK_ALIGNMENT, prev_unpack_alignment);
g_free(flipped_buf);
if (optimal_buf != buf) {
g_free(optimal_buf);
}
if (surface->swizzle) {
g_free(buf);
}

View File

@ -115,8 +115,6 @@ GLSL_DEFINE(sceneAmbientColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_FR_AMB) ".xyz")
GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz")
"\n"
);
mstring_append_fmt(uniforms,
"%smat4 invViewport;\n", u);
/* Skinning */
unsigned int count;
@ -360,7 +358,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
mstring_append_fmt(body,
" float pf;\n"
" if (nDotVP == 0.0) {\n"
" if (nDotVP == 0.0 || nDotHV == 0.0) {\n"
" pf = 0.0;\n"
" } else {\n"
" pf = pow(nDotHV, specularPower);\n"
@ -471,15 +469,16 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
}
mstring_append(body,
" oPos = tPosition * compositeMat;\n"
" oPos.w = clampAwayZeroInf(oPos.w);\n"
" oPos = invViewport * oPos;\n"
" oPos = tPosition * compositeMat;\n"
" oPos.z = oPos.z / clipRange.y;\n"
" oPos.w = clampAwayZeroInf(oPos.w);\n"
" oPos.xy /= oPos.w;\n"
" oPos.xy += c[" stringify(NV_IGRAPH_XF_XFCTX_VPOFF) "].xy;\n"
" oPos.xy = roundScreenCoords(oPos.xy);\n"
" oPos.xy = (2.0f * oPos.xy - surfaceSize) / surfaceSize;\n"
" oPos.xy *= oPos.w;\n"
);
if (state->vulkan) {
mstring_append(body, " oPos.y *= -1;\n");
}
/* FIXME: Testing */
if (state->point_params_enable) {
mstring_append_fmt(uniforms, "%sfloat pointParams[8];\n", u);

View File

@ -639,7 +639,7 @@ static const char* vsh_header =
// Unfortunately mix() falls victim to the same handling of exceptional
// (inf/NaN) handling as a multiply, so per-component comparisons are used
// to guarantee HW behavior (anything * 0 must == 0).
" vec4 zero_components = sign(src0) * sign(src1);\n"
" vec4 zero_components = sign(NaNToOne(src0)) * sign(NaNToOne(src1));\n"
" vec4 ret = src0 * src1;\n"
" if (zero_components.x == 0.0) { ret.x = 0.0; }\n"
" if (zero_components.y == 0.0) { ret.y = 0.0; }\n"
@ -821,22 +821,12 @@ void pgraph_gen_vsh_prog_glsl(uint16_t version,
assert(has_final);
mstring_append(body,
/* the shaders leave the result in screen space, while
* opengl expects it in clip space.
* TODO: the pixel-center co-ordinate differences should handled
/* The shaders leave the result in screen space, while OpenGL expects it
* in clip space.
*/
" oPos.x = 2.0 * (oPos.x - surfaceSize.x * 0.5) / surfaceSize.x;\n"
);
" oPos.xy = roundScreenCoords(oPos.xy);\n"
" oPos.xy = (2.0f * oPos.xy - surfaceSize) / surfaceSize;\n"
if (vulkan) {
mstring_append(body,
" oPos.y = 2.0 * oPos.y / surfaceSize.y - 1.0;\n");
} else {
mstring_append(body, " oPos.y = -2.0 * (oPos.y - surfaceSize.y * 0.5) "
"/ surfaceSize.y;\n");
}
mstring_append(body,
" oPos.z = oPos.z / clipRange.y;\n"
" oPos.w = clampAwayZeroInf(oPos.w);\n"

View File

@ -81,6 +81,17 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs)
" t = clamp(t, uintBitsToFloat(0xDF800000), uintBitsToFloat(0x9F800000));\n"
" }\n"
" return t;\n"
"}\n"
"\n"
"vec4 NaNToOne(vec4 src) {\n"
" return mix(src, vec4(1.0), isnan(src));\n"
"}\n"
"\n"
// Xbox NV2A rasterizer appears to have 4 bit precision fixed-point
// fractional part and to convert floating-point coordinates by
// by truncating (not flooring).
"vec2 roundScreenCoords(vec2 pos) {\n"
" return trunc(pos * 16.0f) / 16.0f;\n"
"}\n");
pgraph_get_glsl_vtx_header(header, state->vulkan, state->smooth_shading,
@ -128,6 +139,7 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs)
}
}
}
mstring_append(header, "\n");
MString *body = mstring_from_str("void main() {\n");
@ -232,17 +244,17 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs)
break;
}
mstring_append(body, " oFog.xyzw = vec4(fogFactor);\n");
mstring_append(body, " oFog = NaNToOne(vec4(fogFactor));\n");
} else {
/* FIXME: Is the fog still calculated / passed somehow?!
*/
mstring_append(body, " oFog.xyzw = vec4(1.0);\n");
mstring_append(body, " oFog = vec4(1.0);\n");
}
/* Set outputs */
mstring_append(body, "\n"
" vtxD0 = clamp(oD0, 0.0, 1.0);\n"
" vtxB0 = clamp(oB0, 0.0, 1.0);\n"
" vtxD0 = clamp(NaNToOne(oD0), 0.0, 1.0);\n"
" vtxB0 = clamp(NaNToOne(oB0), 0.0, 1.0);\n"
" vtxFog = oFog.x;\n"
" vtxT0 = oT0;\n"
" vtxT1 = oT1;\n"
@ -253,8 +265,8 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs)
if (state->specular_enable) {
mstring_append(body,
" vtxD1 = clamp(oD1, 0.0, 1.0);\n"
" vtxB1 = clamp(oB1, 0.0, 1.0);\n"
" vtxD1 = clamp(NaNToOne(oD1), 0.0, 1.0);\n"
" vtxB1 = clamp(NaNToOne(oB1), 0.0, 1.0);\n"
);
if (state->ignore_specular_alpha) {

View File

@ -25,6 +25,8 @@
#endif
#ifdef CONFIG_RENDERDOC
#include "trace/control.h"
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#include "thirdparty/renderdoc_app.h"
#endif
@ -46,11 +48,21 @@ void pgraph_vk_debug_frame_terminator(void)
PGRAPHVkState *r = g_nv2a->pgraph.vk_renderer_state;
if (rdoc_api->IsTargetControlConnected()) {
if (rdoc_api->IsFrameCapturing()) {
bool capturing = rdoc_api->IsFrameCapturing();
if (capturing && renderdoc_capture_frames == 0) {
rdoc_api->EndFrameCapture(RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(r->instance), 0);
if (renderdoc_trace_frames) {
trace_enable_events("-nv2a_pgraph_*");
renderdoc_trace_frames = false;
}
}
if (renderdoc_capture_frames > 0) {
rdoc_api->StartFrameCapture(RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(r->instance), 0);
if (!capturing) {
if (renderdoc_trace_frames) {
trace_enable_events("nv2a_pgraph_*");
}
rdoc_api->StartFrameCapture(RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(r->instance), 0);
}
--renderdoc_capture_frames;
}
}

View File

@ -179,7 +179,6 @@ typedef struct ShaderBinding {
int vsh_constant_loc;
uint32_t vsh_constants[NV2A_VERTEXSHADER_CONSTANTS][4];
int inv_viewport_loc;
int ltctxa_loc;
int ltctxb_loc;
int ltc1_loc;

View File

@ -283,8 +283,6 @@ static void update_shader_constant_locations(ShaderBinding *binding)
binding->fog_param_loc =
uniform_index(&binding->vertex->uniforms, "fogParam");
binding->inv_viewport_loc =
uniform_index(&binding->vertex->uniforms, "invViewport");
binding->ltctxa_loc = uniform_index(&binding->vertex->uniforms, "ltctxa");
binding->ltctxb_loc = uniform_index(&binding->vertex->uniforms, "ltctxb");
binding->ltc1_loc = uniform_index(&binding->vertex->uniforms, "ltc1");
@ -617,27 +615,6 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding,
uniform1f(&binding->vertex->uniforms, binding->specular_power_loc,
pg->specular_power);
}
/* estimate the viewport by assuming it matches the surface ... */
unsigned int aa_width = 1, aa_height = 1;
pgraph_apply_anti_aliasing_factor(pg, &aa_width, &aa_height);
float m11 = 0.5 * (pg->surface_binding_dim.width / aa_width);
float m22 = -0.5 * (pg->surface_binding_dim.height / aa_height);
float m33 = zmax;
float m41 = *(float *)&pg->vsh_constants[NV_IGRAPH_XF_XFCTX_VPOFF][0];
float m42 = *(float *)&pg->vsh_constants[NV_IGRAPH_XF_XFCTX_VPOFF][1];
float invViewport[16] = {
1.0 / m11, 0, 0, 0, 0, 1.0 / m22, 0,
0, 0, 0, 1.0 / m33, 0, -1.0 + m41 / m11, 1.0 + m42 / m22,
0, 1.0
};
if (binding->inv_viewport_loc != -1) {
uniformMatrix4fv(&binding->vertex->uniforms,
binding->inv_viewport_loc, &invViewport[0]);
}
}
/* update vertex program constants */

View File

@ -1,6 +1,6 @@
[wrap-git]
url = https://github.com/KhronosGroup/SPIRV-Reflect
revision = c637858562fbce1b6f5dc7ca48d4e8a5bd117b70
revision = c6c0f5c9796bdef40c55065d82e0df67c38a29a4
depth = 1
[update]

View File

@ -1,4 +1,4 @@
[wrap-git]
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
revision = c788c52156f3ef7bc7ab769cb03c110a53ac8fcb
revision = 1d8f600fd424278486eade7ed3e877c99f0846b1
depth = 1

View File

@ -870,7 +870,7 @@ void xemu_input_update_sdl_controller_state(ControllerState *state)
void xemu_input_update_rumble(ControllerState *state)
{
if (!state->gp.rumble_enabled) {
if (!state->gp.rumble_enabled || !g_config.input.allow_vibration) {
return;
}

View File

@ -500,6 +500,8 @@ void MainMenuInputView::Draw()
SectionTitle("Options");
Toggle("Auto-bind controllers", &g_config.input.auto_bind,
"Bind newly connected controllers to any open port");
Toggle("Controller vibration", &g_config.input.allow_vibration,
"Allows the controllers to vibrate");
Toggle("Background controller input capture",
&g_config.input.background_input_capture,
"Capture even if window is unfocused (requires restart)");

View File

@ -218,7 +218,7 @@ void xemu_hud_render(void)
#if defined(CONFIG_RENDERDOC)
if (g_capture_renderdoc_frame) {
nv2a_dbg_renderdoc_capture_frames(1);
nv2a_dbg_renderdoc_capture_frames(1, false);
g_capture_renderdoc_frame = false;
}
#endif
@ -288,8 +288,10 @@ void xemu_hud_render(void)
g_scene_mgr.PushScene(g_popup_menu);
} else if (menu_button) {
g_scene_mgr.PushScene(g_popup_menu);
} else if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
xemu_toggle_fullscreen();
}
bool mod_key_down = ImGui::IsKeyDown(ImGuiKey_ModShift);
for (int f_key = 0; f_key < 4; ++f_key) {
if (ImGui::IsKeyPressed((enum ImGuiKey)(ImGuiKey_F5 + f_key))) {

View File

@ -73,7 +73,9 @@ void ProcessKeyboardShortcuts(void)
#ifdef CONFIG_RENDERDOC
if (ImGui::IsKeyPressed(ImGuiKey_F10) && nv2a_dbg_renderdoc_available()) {
nv2a_dbg_renderdoc_capture_frames(1);
ImGuiIO& io = ImGui::GetIO();
int num_frames = io.KeyShift ? 5 : 1;
nv2a_dbg_renderdoc_capture_frames(num_frames, io.KeyCtrl);
}
#endif
}