diff --git a/include/config.hpp b/include/config.hpp index 25f352e8..52be1af7 100644 --- a/include/config.hpp +++ b/include/config.hpp @@ -14,7 +14,7 @@ struct EmulatorConfig { #endif // For now, use specialized shaders by default on MacOS as M1 drivers are buggy when using the ubershader, and on Android since mobile GPUs are - // horrible On other platforms we default to ubershader + shadergen fallback for lights + // horrible. On other platforms we default to ubershader + shadergen fallback for lights #if defined(__ANDROID__) || defined(__APPLE__) static constexpr bool ubershaderDefault = false; #else @@ -51,4 +51,4 @@ struct EmulatorConfig { EmulatorConfig(const std::filesystem::path& path); void load(); void save(); -}; \ No newline at end of file +}; diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index bfa9922b..d00445ac 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -117,6 +117,7 @@ class RendererGL final : public Renderer { // Note: The caller is responsible for deleting the currently bound FBO before calling this void setFBO(uint handle) { screenFramebuffer.m_handle = handle; } void resetStateManager() { gl.reset(); } + void clearShaderCache(); void initUbershader(OpenGL::Program& program); #ifdef PANDA3DS_FRONTEND_QT diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 22750f7d..36827027 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -24,10 +24,7 @@ void RendererGL::reset() { colourBufferCache.reset(); textureCache.reset(); - for (auto& shader : shaderCache) { - shader.second.program.free(); - } - shaderCache.clear(); + clearShaderCache(); // Init the colour/depth buffer settings to some random defaults on reset colourBufferLoc = 0; @@ -808,6 +805,8 @@ OpenGL::Program& RendererGL::getSpecializedShader() { program.create({defaultShadergenVs, fragShader}); gl.useProgram(program); + fragShader.free(); + // Init sampler objects. Texture 0 goes in texture unit 0, texture 1 in TU 1, texture 2 in TU 2, and the light maps go in TU 3 glUniform1i(OpenGL::uniformLocation(program, "u_tex0"), 0); glUniform1i(OpenGL::uniformLocation(program, "u_tex1"), 1); @@ -937,16 +936,22 @@ void RendererGL::screenshot(const std::string& name) { stbi_write_png(name.c_str(), width, height, 4, flippedPixels.data(), 0); } +void RendererGL::clearShaderCache() { + for (auto& shader : shaderCache) { + CachedProgram& cachedProgram = shader.second; + cachedProgram.program.free(); + glDeleteBuffers(1, &cachedProgram.uboBinding); + } + + shaderCache.clear(); +} + void RendererGL::deinitGraphicsContext() { // Invalidate all surface caches since they'll no longer be valid textureCache.reset(); depthBufferCache.reset(); colourBufferCache.reset(); - - for (auto& shader : shaderCache) { - shader.second.program.free(); - } - shaderCache.clear(); + clearShaderCache(); // All other GL objects should be invalidated automatically and be recreated by the next call to initGraphicsContext // TODO: Make it so that depth and colour buffers get written back to 3DS memory diff --git a/src/host_shaders/opengl_fragment_shader.frag b/src/host_shaders/opengl_fragment_shader.frag index 9f369e39..48b55a4c 100644 --- a/src/host_shaders/opengl_fragment_shader.frag +++ b/src/host_shaders/opengl_fragment_shader.frag @@ -307,8 +307,8 @@ void calcLighting(out vec4 primary_color, out vec4 secondary_color) { primary_color = vec4(vec3(0.0), 1.0); secondary_color = vec4(vec3(0.0), 1.0); - uint GPUREG_LIGHTING_LUTINPUT_SCALE = readPicaReg(0x01D2u); uint GPUREG_LIGHTING_CONFIG0 = readPicaReg(0x01C3u); + GPUREG_LIGHTING_LUTINPUT_SCALE = readPicaReg(0x01D2u); GPUREG_LIGHTING_CONFIG1 = readPicaReg(0x01C4u); GPUREG_LIGHTING_LUTINPUT_ABS = readPicaReg(0x01D0u); GPUREG_LIGHTING_LUTINPUT_SELECT = readPicaReg(0x01D1u); diff --git a/src/libretro_core.cpp b/src/libretro_core.cpp index 02bf3cd1..3e0436b8 100644 --- a/src/libretro_core.cpp +++ b/src/libretro_core.cpp @@ -15,6 +15,8 @@ static retro_input_state_t inputStateCallback; static retro_hw_render_callback hw_render; static std::filesystem::path savePath; +static bool screenTouched; + std::unique_ptr emulator; RendererGL* renderer; @@ -314,7 +316,8 @@ void retro_run() { hid.setCirclepadX((xLeft / +32767) * 0x9C); hid.setCirclepadY((yLeft / -32767) * 0x9C); - bool touch = inputStateCallback(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT); + bool touchScreen = false; + const int posX = inputStateCallback(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X); const int posY = inputStateCallback(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y); @@ -324,16 +327,23 @@ void retro_run() { const int offsetX = 40; const int offsetY = emulator->height / 2; - const bool inScreenX = newX >= offsetX && newX < emulator->width - offsetX; + const bool inScreenX = newX >= offsetX && newX <= emulator->width - offsetX; const bool inScreenY = newY >= offsetY && newY <= emulator->height; - if (touch && inScreenX && inScreenY) { + if (inScreenX && inScreenY) { + touchScreen |= inputStateCallback(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT); + touchScreen |= inputStateCallback(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED); + } + + if (touchScreen) { u16 x = static_cast(newX - offsetX); u16 y = static_cast(newY - offsetY); hid.setTouchScreenPress(x, y); - } else { + screenTouched = true; + } else if (screenTouched) { hid.releaseTouchScreen(); + screenTouched = false; } hid.updateInputs(emulator->getTicks());