diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index 96644b534..d729f40b2 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -209,6 +209,7 @@ bool GPU_HW::Initialize() m_wireframe_mode = g_settings.gpu_wireframe_mode; m_disable_color_perspective = features.noperspective_interpolation && ShouldDisableColorPerspective(); m_pgxp_depth_buffer = g_settings.UsingPGXPDepthBuffer(); + m_allow_sprite_mode = true; CheckSettings(); @@ -793,7 +794,7 @@ bool GPU_HW::CompilePipelines() m_disable_color_perspective, m_supports_dual_source_blend, m_supports_framebuffer_fetch, m_debanding); - constexpr u32 active_texture_modes = 4; + const u32 active_texture_modes = m_allow_sprite_mode ? 7 : 4; const u32 total_pipelines = 2 + // vertex shaders (active_texture_modes * 5 * 9 * 2 * 2 * 2) + // fragment shaders @@ -865,11 +866,14 @@ bool GPU_HW::CompilePipelines() { for (u8 interlacing = 0; interlacing < 2; interlacing++) { + const bool sprite = (static_cast(texture_mode) >= BatchTextureMode::SpriteStart); + const BatchTextureMode shader_texmode = static_cast( + texture_mode - (sprite ? static_cast(BatchTextureMode::SpriteStart) : 0)); const std::string fs = shadergen.GenerateBatchFragmentShader( static_cast(render_mode), static_cast(transparency_mode), - static_cast(texture_mode), m_texture_filtering, m_force_round_texcoords, - ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing), - ConvertToBoolUnchecked(check_mask)); + shader_texmode, sprite ? GPUTextureFilter::Nearest : m_texture_filtering, + sprite && m_force_round_texcoords, ConvertToBoolUnchecked(dithering), + ConvertToBoolUnchecked(interlacing), ConvertToBoolUnchecked(check_mask)); if (!(batch_fragment_shaders[render_mode][transparency_mode][texture_mode][check_mask][dithering] [interlacing] = g_gpu_device->CreateShader(GPUShaderStage::Fragment, @@ -1519,12 +1523,15 @@ ALWAYS_INLINE_RELEASE void GPU_HW::DrawBatchVertices(BatchRenderMode render_mode u32 base_vertex) { // [depth_test][transparency_mode][render_mode][texture_mode][dithering][interlacing][check_mask] + const u8 texture_mode = static_cast(m_batch.texture_mode) + + ((m_batch.texture_mode != BatchTextureMode::Disabled && m_batch.sprite_mode) ? + static_cast(BatchTextureMode::SpriteStart) : + 0); const u8 depth_test = BoolToUInt8(m_batch.use_depth_buffer); const u8 check_mask = BoolToUInt8(m_batch.check_mask_before_draw); g_gpu_device->SetPipeline(m_batch_pipelines[depth_test][static_cast(m_batch.transparency_mode)][static_cast( - render_mode)][static_cast(m_batch.texture_mode)][BoolToUInt8(m_batch.dithering)] - [BoolToUInt8(m_batch.interlacing)][check_mask] - .get()); + render_mode)][texture_mode][BoolToUInt8(m_batch.dithering)][BoolToUInt8(m_batch.interlacing)][check_mask] + .get()); if (render_mode != BatchRenderMode::ShaderBlend || m_supports_framebuffer_fetch) g_gpu_device->DrawIndexed(num_indices, base_index, base_vertex); @@ -1844,6 +1851,23 @@ void GPU_HW::CheckForDepthClear(const BatchVertex* vertices, u32 num_vertices) m_last_depth_z = average_z; } +void GPU_HW::SetBatchSpriteMode(bool enabled) +{ + if (m_batch.sprite_mode == enabled) + return; + + if (m_batch_index_count > 0) + { + FlushRender(); + EnsureVertexBufferSpaceForCurrentCommand(); + } + + WARNING_LOG("Sprite mode {}", enabled); + GL_INS_FMT("SPRITE MODE {}", enabled); + + m_batch.sprite_mode = enabled; +} + u32 GPU_HW::GetAdaptiveDownsamplingMipLevels() const { u32 levels = 0; @@ -2000,6 +2024,7 @@ void GPU_HW::LoadVertices() } if (pgxp) { + SetBatchSpriteMode(m_allow_sprite_mode && !valid_w); if (!valid_w) { SetBatchDepthBuffer(false); @@ -2180,6 +2205,7 @@ void GPU_HW::LoadVertices() // we can split the rectangle up into potentially 8 quads SetBatchDepthBuffer(false); + SetBatchSpriteMode(m_allow_sprite_mode); DebugAssert(m_batch_vertex_space >= MAX_VERTICES_FOR_RECTANGLE && m_batch_index_space >= MAX_VERTICES_FOR_RECTANGLE); diff --git a/src/core/gpu_hw.h b/src/core/gpu_hw.h index 3d497dac2..52bd452b5 100644 --- a/src/core/gpu_hw.h +++ b/src/core/gpu_hw.h @@ -40,7 +40,13 @@ public: Direct16Bit, Disabled, + SpritePalette4Bit, + SpritePalette8Bit, + SpriteDirect16Bit, + MaxCount, + + SpriteStart = SpritePalette4Bit, }; static_assert(static_cast(BatchTextureMode::Palette4Bit) == static_cast(GPUTextureMode::Palette4Bit) && static_cast(BatchTextureMode::Palette8Bit) == static_cast(GPUTextureMode::Palette8Bit) && @@ -108,6 +114,7 @@ private: bool set_mask_while_drawing = false; bool check_mask_before_draw = false; bool use_depth_buffer = false; + bool sprite_mode = false; // Returns the render mode for this batch. BatchRenderMode GetRenderMode() const; @@ -209,6 +216,7 @@ private: /// Sets the depth test flag for PGXP depth buffering. void SetBatchDepthBuffer(bool enabled); void CheckForDepthClear(const BatchVertex* vertices, u32 num_vertices); + void SetBatchSpriteMode(bool enabled); /// Returns the number of mipmap levels used for adaptive smoothing. u32 GetAdaptiveDownsamplingMipLevels() const; @@ -259,6 +267,7 @@ private: bool m_clamp_uvs : 1 = false; bool m_compute_uv_range : 1 = false; bool m_pgxp_depth_buffer : 1 = false; + bool m_allow_sprite_mode : 1 = false; bool m_allow_shader_blend : 1 = false; bool m_prefer_shader_blend : 1 = false; u8 m_texpage_dirty = 0;