GPU: Implement interlaced rendering in hardware backends
This commit is contained in:
parent
bb3c0a2ccc
commit
2aecb570c1
|
@ -627,12 +627,12 @@ void GPU::Execute(TickCount ticks)
|
||||||
// alternating even line bit in 240-line mode
|
// alternating even line bit in 240-line mode
|
||||||
if (m_GPUSTAT.In480iMode())
|
if (m_GPUSTAT.In480iMode())
|
||||||
{
|
{
|
||||||
m_GPUSTAT.drawing_even_line =
|
m_GPUSTAT.displaying_odd_line =
|
||||||
ConvertToBoolUnchecked((m_crtc_state.regs.Y + BoolToUInt32(!m_GPUSTAT.interlaced_field)) & u32(1));
|
ConvertToBoolUnchecked((m_crtc_state.regs.Y + BoolToUInt32(m_GPUSTAT.interlaced_field)) & u32(1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_GPUSTAT.drawing_even_line =
|
m_GPUSTAT.displaying_odd_line =
|
||||||
ConvertToBoolUnchecked((m_crtc_state.regs.Y + m_crtc_state.current_scanline) & u32(1));
|
ConvertToBoolUnchecked((m_crtc_state.regs.Y + m_crtc_state.current_scanline) & u32(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -995,6 +995,9 @@ void GPU::SetDrawMode(u16 value)
|
||||||
|
|
||||||
m_draw_mode.mode_reg.bits = new_mode_reg.bits;
|
m_draw_mode.mode_reg.bits = new_mode_reg.bits;
|
||||||
|
|
||||||
|
if (m_GPUSTAT.draw_to_displayed_field != new_mode_reg.draw_to_displayed_field)
|
||||||
|
FlushRender();
|
||||||
|
|
||||||
// Bits 0..10 are returned in the GPU status register.
|
// Bits 0..10 are returned in the GPU status register.
|
||||||
m_GPUSTAT.bits =
|
m_GPUSTAT.bits =
|
||||||
(m_GPUSTAT.bits & ~(DrawMode::Reg::GPUSTAT_MASK)) | (ZeroExtend32(new_mode_reg.bits) & DrawMode::Reg::GPUSTAT_MASK);
|
(m_GPUSTAT.bits & ~(DrawMode::Reg::GPUSTAT_MASK)) | (ZeroExtend32(new_mode_reg.bits) & DrawMode::Reg::GPUSTAT_MASK);
|
||||||
|
@ -1124,7 +1127,7 @@ void GPU::DrawDebugStateWindow()
|
||||||
ImGui::Text("Vertical Interlace: %s (%s field)", m_GPUSTAT.vertical_interlace ? "Yes" : "No",
|
ImGui::Text("Vertical Interlace: %s (%s field)", m_GPUSTAT.vertical_interlace ? "Yes" : "No",
|
||||||
m_GPUSTAT.interlaced_field ? "odd" : "even");
|
m_GPUSTAT.interlaced_field ? "odd" : "even");
|
||||||
ImGui::Text("Display Disable: %s", m_GPUSTAT.display_disable ? "Yes" : "No");
|
ImGui::Text("Display Disable: %s", m_GPUSTAT.display_disable ? "Yes" : "No");
|
||||||
ImGui::Text("Drawing Even Line: %s", m_GPUSTAT.drawing_even_line ? "Yes" : "No");
|
ImGui::Text("Displaying Odd Line/Field: %s", m_GPUSTAT.displaying_odd_line ? "Yes" : "No");
|
||||||
ImGui::Text("Color Depth: %u-bit", m_GPUSTAT.display_area_color_depth_24 ? 24 : 15);
|
ImGui::Text("Color Depth: %u-bit", m_GPUSTAT.display_area_color_depth_24 ? 24 : 15);
|
||||||
ImGui::Text("Start Offset: (%u, %u)", cs.regs.X.GetValue(), cs.regs.Y.GetValue());
|
ImGui::Text("Start Offset: (%u, %u)", cs.regs.X.GetValue(), cs.regs.Y.GetValue());
|
||||||
ImGui::Text("Display Total: %u (%u) horizontal, %u vertical", cs.horizontal_total,
|
ImGui::Text("Display Total: %u (%u) horizontal, %u vertical", cs.horizontal_total,
|
||||||
|
@ -1145,7 +1148,7 @@ void GPU::DrawDebugStateWindow()
|
||||||
if (ImGui::CollapsingHeader("GPU", ImGuiTreeNodeFlags_DefaultOpen))
|
if (ImGui::CollapsingHeader("GPU", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
{
|
{
|
||||||
ImGui::Text("Dither: %s", m_GPUSTAT.dither_enable ? "Enabled" : "Disabled");
|
ImGui::Text("Dither: %s", m_GPUSTAT.dither_enable ? "Enabled" : "Disabled");
|
||||||
ImGui::Text("Draw To Display Area: %s", m_GPUSTAT.draw_to_display_area ? "Enabled" : "Disabled");
|
ImGui::Text("Draw To Displayed Field: %s", m_GPUSTAT.draw_to_displayed_field ? "Enabled" : "Disabled");
|
||||||
ImGui::Text("Draw Set Mask Bit: %s", m_GPUSTAT.set_mask_while_drawing ? "Yes" : "No");
|
ImGui::Text("Draw Set Mask Bit: %s", m_GPUSTAT.set_mask_while_drawing ? "Yes" : "No");
|
||||||
ImGui::Text("Draw To Masked Pixels: %s", m_GPUSTAT.check_mask_before_draw ? "Yes" : "No");
|
ImGui::Text("Draw To Masked Pixels: %s", m_GPUSTAT.check_mask_before_draw ? "Yes" : "No");
|
||||||
ImGui::Text("Reverse Flag: %s", m_GPUSTAT.reverse_flag ? "Yes" : "No");
|
ImGui::Text("Reverse Flag: %s", m_GPUSTAT.reverse_flag ? "Yes" : "No");
|
||||||
|
|
|
@ -377,7 +377,7 @@ protected:
|
||||||
BitField<u32, TransparencyMode, 5, 2> semi_transparency_mode;
|
BitField<u32, TransparencyMode, 5, 2> semi_transparency_mode;
|
||||||
BitField<u32, TextureMode, 7, 2> texture_color_mode;
|
BitField<u32, TextureMode, 7, 2> texture_color_mode;
|
||||||
BitField<u32, bool, 9, 1> dither_enable;
|
BitField<u32, bool, 9, 1> dither_enable;
|
||||||
BitField<u32, bool, 10, 1> draw_to_display_area;
|
BitField<u32, bool, 10, 1> draw_to_displayed_field;
|
||||||
BitField<u32, bool, 11, 1> set_mask_while_drawing;
|
BitField<u32, bool, 11, 1> set_mask_while_drawing;
|
||||||
BitField<u32, bool, 12, 1> check_mask_before_draw;
|
BitField<u32, bool, 12, 1> check_mask_before_draw;
|
||||||
BitField<u32, bool, 13, 1> interlaced_field;
|
BitField<u32, bool, 13, 1> interlaced_field;
|
||||||
|
@ -396,7 +396,7 @@ protected:
|
||||||
BitField<u32, bool, 27, 1> ready_to_send_vram;
|
BitField<u32, bool, 27, 1> ready_to_send_vram;
|
||||||
BitField<u32, bool, 28, 1> ready_to_recieve_dma;
|
BitField<u32, bool, 28, 1> ready_to_recieve_dma;
|
||||||
BitField<u32, DMADirection, 29, 2> dma_direction;
|
BitField<u32, DMADirection, 29, 2> dma_direction;
|
||||||
BitField<u32, bool, 31, 1> drawing_even_line;
|
BitField<u32, bool, 31, 1> displaying_odd_line;
|
||||||
|
|
||||||
bool IsMaskingEnabled() const
|
bool IsMaskingEnabled() const
|
||||||
{
|
{
|
||||||
|
@ -452,7 +452,7 @@ protected:
|
||||||
BitField<u16, TransparencyMode, 5, 2> transparency_mode;
|
BitField<u16, TransparencyMode, 5, 2> transparency_mode;
|
||||||
BitField<u16, TextureMode, 7, 2> texture_mode;
|
BitField<u16, TextureMode, 7, 2> texture_mode;
|
||||||
BitField<u16, bool, 9, 1> dither_enable;
|
BitField<u16, bool, 9, 1> dither_enable;
|
||||||
BitField<u16, bool, 10, 1> draw_to_display_area;
|
BitField<u16, bool, 10, 1> draw_to_displayed_field;
|
||||||
BitField<u16, bool, 11, 1> texture_disable;
|
BitField<u16, bool, 11, 1> texture_disable;
|
||||||
BitField<u16, bool, 12, 1> texture_x_flip;
|
BitField<u16, bool, 12, 1> texture_x_flip;
|
||||||
BitField<u16, bool, 13, 1> texture_y_flip;
|
BitField<u16, bool, 13, 1> texture_y_flip;
|
||||||
|
|
|
@ -541,6 +541,14 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
|
||||||
m_batch_ubo_dirty = true;
|
m_batch_ubo_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_batch.interlacing = m_GPUSTAT.SkipDrawingToActiveField();
|
||||||
|
if (m_batch.interlacing)
|
||||||
|
{
|
||||||
|
const u32 displayed_field = BoolToUInt32(m_GPUSTAT.displaying_odd_line);
|
||||||
|
m_batch_ubo_dirty |= (m_batch_ubo_data.u_interlaced_displayed_field != displayed_field);
|
||||||
|
m_batch_ubo_data.u_interlaced_displayed_field = displayed_field;
|
||||||
|
}
|
||||||
|
|
||||||
// update state
|
// update state
|
||||||
m_batch.primitive = rc_primitive;
|
m_batch.primitive = rc_primitive;
|
||||||
m_batch.texture_mode = texture_mode;
|
m_batch.texture_mode = texture_mode;
|
||||||
|
|
|
@ -76,6 +76,7 @@ protected:
|
||||||
TextureMode texture_mode;
|
TextureMode texture_mode;
|
||||||
TransparencyMode transparency_mode;
|
TransparencyMode transparency_mode;
|
||||||
bool dithering;
|
bool dithering;
|
||||||
|
bool interlacing;
|
||||||
bool set_mask_while_drawing;
|
bool set_mask_while_drawing;
|
||||||
bool check_mask_before_draw;
|
bool check_mask_before_draw;
|
||||||
|
|
||||||
|
@ -102,7 +103,7 @@ protected:
|
||||||
float u_src_alpha_factor;
|
float u_src_alpha_factor;
|
||||||
float u_dst_alpha_factor;
|
float u_dst_alpha_factor;
|
||||||
u32 u_set_mask_while_drawing;
|
u32 u_set_mask_while_drawing;
|
||||||
u32 padding[1];
|
u32 u_interlaced_displayed_field;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RendererStats
|
struct RendererStats
|
||||||
|
|
|
@ -349,13 +349,17 @@ bool GPU_HW_D3D11::CompileShaders()
|
||||||
{
|
{
|
||||||
for (u8 dithering = 0; dithering < 2; dithering++)
|
for (u8 dithering = 0; dithering < 2; dithering++)
|
||||||
{
|
{
|
||||||
const std::string ps = shadergen.GenerateBatchFragmentShader(static_cast<BatchRenderMode>(render_mode),
|
for (u8 interlacing = 0; interlacing < 2; interlacing++)
|
||||||
static_cast<TextureMode>(texture_mode),
|
{
|
||||||
ConvertToBoolUnchecked(dithering));
|
const std::string ps = shadergen.GenerateBatchFragmentShader(
|
||||||
|
static_cast<BatchRenderMode>(render_mode), static_cast<TextureMode>(texture_mode),
|
||||||
|
ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing));
|
||||||
|
|
||||||
m_batch_pixel_shaders[render_mode][texture_mode][dithering] = m_shader_cache.GetPixelShader(m_device.Get(), ps);
|
m_batch_pixel_shaders[render_mode][texture_mode][dithering][interlacing] =
|
||||||
if (!m_batch_pixel_shaders[render_mode][texture_mode][dithering])
|
m_shader_cache.GetPixelShader(m_device.Get(), ps);
|
||||||
return false;
|
if (!m_batch_pixel_shaders[render_mode][texture_mode][dithering][interlacing])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,12 +392,12 @@ bool GPU_HW_D3D11::CompileShaders()
|
||||||
|
|
||||||
for (u8 depth_24bit = 0; depth_24bit < 2; depth_24bit++)
|
for (u8 depth_24bit = 0; depth_24bit < 2; depth_24bit++)
|
||||||
{
|
{
|
||||||
for (u8 interlaced = 0; interlaced < 2; interlaced++)
|
for (u8 interlacing = 0; interlacing < 2; interlacing++)
|
||||||
{
|
{
|
||||||
const std::string ps = shadergen.GenerateDisplayFragmentShader(ConvertToBoolUnchecked(depth_24bit),
|
const std::string ps = shadergen.GenerateDisplayFragmentShader(ConvertToBoolUnchecked(depth_24bit),
|
||||||
ConvertToBoolUnchecked(interlaced));
|
ConvertToBoolUnchecked(interlacing));
|
||||||
m_display_pixel_shaders[depth_24bit][interlaced] = m_shader_cache.GetPixelShader(m_device.Get(), ps);
|
m_display_pixel_shaders[depth_24bit][interlacing] = m_shader_cache.GetPixelShader(m_device.Get(), ps);
|
||||||
if (!m_display_pixel_shaders[depth_24bit][interlaced])
|
if (!m_display_pixel_shaders[depth_24bit][interlacing])
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -486,7 +490,7 @@ void GPU_HW_D3D11::SetDrawState(BatchRenderMode render_mode)
|
||||||
nullptr, 0);
|
nullptr, 0);
|
||||||
|
|
||||||
m_context->PSSetShader(m_batch_pixel_shaders[static_cast<u8>(render_mode)][static_cast<u8>(m_batch.texture_mode)]
|
m_context->PSSetShader(m_batch_pixel_shaders[static_cast<u8>(render_mode)][static_cast<u8>(m_batch.texture_mode)]
|
||||||
[BoolToUInt8(m_batch.dithering)]
|
[BoolToUInt8(m_batch.dithering)][BoolToUInt8(m_batch.interlacing)]
|
||||||
.Get(),
|
.Get(),
|
||||||
nullptr, 0);
|
nullptr, 0);
|
||||||
|
|
||||||
|
@ -555,8 +559,7 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||||
m_context->OMSetRenderTargets(1, m_display_texture.GetD3DRTVArray(), nullptr);
|
m_context->OMSetRenderTargets(1, m_display_texture.GetD3DRTVArray(), nullptr);
|
||||||
m_context->PSSetShaderResources(0, 1, m_vram_texture.GetD3DSRVArray());
|
m_context->PSSetShaderResources(0, 1, m_vram_texture.GetD3DSRVArray());
|
||||||
|
|
||||||
const u32 reinterpret_field_offset =
|
const u32 reinterpret_field_offset = BoolToUInt32(m_GPUSTAT.displaying_odd_line);
|
||||||
(m_crtc_state.regs.Y + BoolToUInt8(interlaced && m_GPUSTAT.interlaced_field)) & 1u;
|
|
||||||
const u32 reinterpret_start_x = m_crtc_state.regs.X * m_resolution_scale;
|
const u32 reinterpret_start_x = m_crtc_state.regs.X * m_resolution_scale;
|
||||||
const u32 reinterpret_width = scaled_display_width + (m_crtc_state.display_vram_left - m_crtc_state.regs.X);
|
const u32 reinterpret_width = scaled_display_width + (m_crtc_state.display_vram_left - m_crtc_state.regs.X);
|
||||||
const u32 uniforms[4] = {reinterpret_field_offset, reinterpret_start_x};
|
const u32 uniforms[4] = {reinterpret_field_offset, reinterpret_start_x};
|
||||||
|
|
|
@ -103,8 +103,8 @@ private:
|
||||||
std::array<ComPtr<ID3D11BlendState>, 5> m_batch_blend_states; // [transparency_mode]
|
std::array<ComPtr<ID3D11BlendState>, 5> m_batch_blend_states; // [transparency_mode]
|
||||||
ComPtr<ID3D11InputLayout> m_batch_input_layout;
|
ComPtr<ID3D11InputLayout> m_batch_input_layout;
|
||||||
std::array<ComPtr<ID3D11VertexShader>, 2> m_batch_vertex_shaders; // [textured]
|
std::array<ComPtr<ID3D11VertexShader>, 2> m_batch_vertex_shaders; // [textured]
|
||||||
std::array<std::array<std::array<ComPtr<ID3D11PixelShader>, 2>, 9>, 4>
|
std::array<std::array<std::array<std::array<ComPtr<ID3D11PixelShader>, 2>, 2>, 9>, 4>
|
||||||
m_batch_pixel_shaders; // [render_mode][texture_mode][dithering]
|
m_batch_pixel_shaders; // [render_mode][texture_mode][dithering][interlacing]
|
||||||
ComPtr<ID3D11GeometryShader> m_batch_line_expand_geometry_shader;
|
ComPtr<ID3D11GeometryShader> m_batch_line_expand_geometry_shader;
|
||||||
|
|
||||||
ComPtr<ID3D11VertexShader> m_screen_quad_vertex_shader;
|
ComPtr<ID3D11VertexShader> m_screen_quad_vertex_shader;
|
||||||
|
|
|
@ -302,35 +302,38 @@ bool GPU_HW_OpenGL::CompilePrograms()
|
||||||
{
|
{
|
||||||
for (u8 dithering = 0; dithering < 2; dithering++)
|
for (u8 dithering = 0; dithering < 2; dithering++)
|
||||||
{
|
{
|
||||||
const bool textured = (static_cast<TextureMode>(texture_mode) != TextureMode::Disabled);
|
for (u8 interlacing = 0; interlacing < 2; interlacing++)
|
||||||
const std::string vs = shadergen.GenerateBatchVertexShader(textured);
|
{
|
||||||
const std::string fs = shadergen.GenerateBatchFragmentShader(static_cast<BatchRenderMode>(render_mode),
|
const bool textured = (static_cast<TextureMode>(texture_mode) != TextureMode::Disabled);
|
||||||
static_cast<TextureMode>(texture_mode),
|
const std::string vs = shadergen.GenerateBatchVertexShader(textured);
|
||||||
ConvertToBoolUnchecked(dithering));
|
const std::string fs = shadergen.GenerateBatchFragmentShader(
|
||||||
|
static_cast<BatchRenderMode>(render_mode), static_cast<TextureMode>(texture_mode),
|
||||||
|
ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing));
|
||||||
|
|
||||||
std::optional<GL::Program> prog = m_shader_cache.GetProgram(vs, fs, [this, textured](GL::Program& prog) {
|
std::optional<GL::Program> prog = m_shader_cache.GetProgram(vs, fs, [this, textured](GL::Program& prog) {
|
||||||
prog.BindAttribute(0, "a_pos");
|
prog.BindAttribute(0, "a_pos");
|
||||||
prog.BindAttribute(1, "a_col0");
|
prog.BindAttribute(1, "a_col0");
|
||||||
|
if (textured)
|
||||||
|
{
|
||||||
|
prog.BindAttribute(2, "a_texcoord");
|
||||||
|
prog.BindAttribute(3, "a_texpage");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_is_gles)
|
||||||
|
prog.BindFragData(0, "o_col0");
|
||||||
|
});
|
||||||
|
if (!prog)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
prog->BindUniformBlock("UBOBlock", 1);
|
||||||
if (textured)
|
if (textured)
|
||||||
{
|
{
|
||||||
prog.BindAttribute(2, "a_texcoord");
|
prog->Bind();
|
||||||
prog.BindAttribute(3, "a_texpage");
|
prog->Uniform1i("samp0", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_is_gles)
|
m_render_programs[render_mode][texture_mode][dithering][interlacing] = std::move(*prog);
|
||||||
prog.BindFragData(0, "o_col0");
|
|
||||||
});
|
|
||||||
if (!prog)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
prog->BindUniformBlock("UBOBlock", 1);
|
|
||||||
if (textured)
|
|
||||||
{
|
|
||||||
prog->Bind();
|
|
||||||
prog->Uniform1i("samp0", 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_render_programs[render_mode][texture_mode][dithering] = std::move(*prog);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,7 +409,7 @@ bool GPU_HW_OpenGL::CompilePrograms()
|
||||||
void GPU_HW_OpenGL::SetDrawState(BatchRenderMode render_mode)
|
void GPU_HW_OpenGL::SetDrawState(BatchRenderMode render_mode)
|
||||||
{
|
{
|
||||||
const GL::Program& prog = m_render_programs[static_cast<u8>(render_mode)][static_cast<u8>(m_batch.texture_mode)]
|
const GL::Program& prog = m_render_programs[static_cast<u8>(render_mode)][static_cast<u8>(m_batch.texture_mode)]
|
||||||
[BoolToUInt8(m_batch.dithering)];
|
[BoolToUInt8(m_batch.dithering)][BoolToUInt8(m_batch.interlacing)];
|
||||||
prog.Bind();
|
prog.Bind();
|
||||||
|
|
||||||
if (m_batch.texture_mode != TextureMode::Disabled)
|
if (m_batch.texture_mode != TextureMode::Disabled)
|
||||||
|
@ -513,8 +516,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||||
const u32 scaled_flipped_vram_offset_y =
|
const u32 scaled_flipped_vram_offset_y =
|
||||||
m_vram_texture.GetHeight() - scaled_vram_offset_y - scaled_display_height;
|
m_vram_texture.GetHeight() - scaled_vram_offset_y - scaled_display_height;
|
||||||
|
|
||||||
const u32 reinterpret_field_offset =
|
const u32 reinterpret_field_offset = BoolToUInt32(m_GPUSTAT.displaying_odd_line);
|
||||||
(m_crtc_state.regs.Y + BoolToUInt8(interlaced && m_GPUSTAT.interlaced_field)) & 1u;
|
|
||||||
const u32 reinterpret_start_x = m_crtc_state.regs.X * m_resolution_scale;
|
const u32 reinterpret_start_x = m_crtc_state.regs.X * m_resolution_scale;
|
||||||
const u32 reinterpret_width = scaled_display_width + (m_crtc_state.display_vram_left - m_crtc_state.regs.X);
|
const u32 reinterpret_width = scaled_display_width + (m_crtc_state.display_vram_left - m_crtc_state.regs.X);
|
||||||
const u32 uniforms[4] = {reinterpret_field_offset, reinterpret_start_x};
|
const u32 uniforms[4] = {reinterpret_field_offset, reinterpret_start_x};
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common/gl/program.h"
|
#include "common/gl/program.h"
|
||||||
|
#include "common/gl/shader_cache.h"
|
||||||
#include "common/gl/stream_buffer.h"
|
#include "common/gl/stream_buffer.h"
|
||||||
#include "common/gl/texture.h"
|
#include "common/gl/texture.h"
|
||||||
#include "common/gl/shader_cache.h"
|
|
||||||
#include "glad.h"
|
#include "glad.h"
|
||||||
#include "gpu_hw.h"
|
#include "gpu_hw.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
@ -76,8 +76,9 @@ private:
|
||||||
std::unique_ptr<GL::StreamBuffer> m_texture_stream_buffer;
|
std::unique_ptr<GL::StreamBuffer> m_texture_stream_buffer;
|
||||||
GLuint m_texture_buffer_r16ui_texture = 0;
|
GLuint m_texture_buffer_r16ui_texture = 0;
|
||||||
|
|
||||||
std::array<std::array<std::array<GL::Program, 2>, 9>, 4> m_render_programs; // [render_mode][texture_mode][dithering]
|
std::array<std::array<std::array<std::array<GL::Program, 2>, 2>, 9>, 4>
|
||||||
std::array<std::array<GL::Program, 2>, 2> m_display_programs; // [depth_24][interlaced]
|
m_render_programs; // [render_mode][texture_mode][dithering][interlacing]
|
||||||
|
std::array<std::array<GL::Program, 2>, 2> m_display_programs; // [depth_24][interlaced]
|
||||||
GL::Program m_vram_read_program;
|
GL::Program m_vram_read_program;
|
||||||
GL::Program m_vram_write_program;
|
GL::Program m_vram_write_program;
|
||||||
|
|
||||||
|
|
|
@ -197,35 +197,39 @@ bool GPU_HW_OpenGL_ES::CompilePrograms()
|
||||||
{
|
{
|
||||||
for (u8 dithering = 0; dithering < 2; dithering++)
|
for (u8 dithering = 0; dithering < 2; dithering++)
|
||||||
{
|
{
|
||||||
const bool textured = (static_cast<TextureMode>(texture_mode) != TextureMode::Disabled);
|
for (u8 interlacing = 0; interlacing < 2; interlacing++)
|
||||||
const std::string vs = shadergen.GenerateBatchVertexShader(textured);
|
{
|
||||||
const std::string fs = shadergen.GenerateBatchFragmentShader(static_cast<BatchRenderMode>(render_mode),
|
const bool textured = (static_cast<TextureMode>(texture_mode) != TextureMode::Disabled);
|
||||||
static_cast<TextureMode>(texture_mode),
|
const std::string vs = shadergen.GenerateBatchVertexShader(textured);
|
||||||
ConvertToBoolUnchecked(dithering));
|
const std::string fs = shadergen.GenerateBatchFragmentShader(
|
||||||
|
static_cast<BatchRenderMode>(render_mode), static_cast<TextureMode>(texture_mode),
|
||||||
|
ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing));
|
||||||
|
|
||||||
|
std::optional<GL::Program> prog = m_shader_cache.GetProgram(vs, fs, [this, textured](GL::Program& prog) {
|
||||||
|
prog.BindAttribute(0, "a_pos");
|
||||||
|
prog.BindAttribute(1, "a_col0");
|
||||||
|
if (textured)
|
||||||
|
{
|
||||||
|
prog.BindAttribute(2, "a_texcoord");
|
||||||
|
prog.BindAttribute(3, "a_texpage");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!prog)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
prog->Bind();
|
||||||
|
prog->RegisterUniform("u_texture_window_mask");
|
||||||
|
prog->RegisterUniform("u_texture_window_offset");
|
||||||
|
prog->RegisterUniform("u_src_alpha_factor");
|
||||||
|
prog->RegisterUniform("u_dst_alpha_factor");
|
||||||
|
prog->RegisterUniform("u_set_mask_while_drawing");
|
||||||
|
prog->RegisterUniform("u_interlaced_displayed_field");
|
||||||
|
|
||||||
std::optional<GL::Program> prog = m_shader_cache.GetProgram(vs, fs, [this, textured](GL::Program& prog) {
|
|
||||||
prog.BindAttribute(0, "a_pos");
|
|
||||||
prog.BindAttribute(1, "a_col0");
|
|
||||||
if (textured)
|
if (textured)
|
||||||
{
|
prog->Uniform1i("samp0", 0);
|
||||||
prog.BindAttribute(2, "a_texcoord");
|
|
||||||
prog.BindAttribute(3, "a_texpage");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!prog)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
prog->Bind();
|
m_render_programs[render_mode][texture_mode][dithering][interlacing] = std::move(*prog);
|
||||||
prog->RegisterUniform("u_texture_window_mask");
|
}
|
||||||
prog->RegisterUniform("u_texture_window_offset");
|
|
||||||
prog->RegisterUniform("u_src_alpha_factor");
|
|
||||||
prog->RegisterUniform("u_dst_alpha_factor");
|
|
||||||
prog->RegisterUniform("u_set_mask_while_drawing");
|
|
||||||
|
|
||||||
if (textured)
|
|
||||||
prog->Uniform1i("samp0", 0);
|
|
||||||
|
|
||||||
m_render_programs[render_mode][texture_mode][dithering] = std::move(*prog);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,7 +281,7 @@ void GPU_HW_OpenGL_ES::SetVertexPointers()
|
||||||
void GPU_HW_OpenGL_ES::SetDrawState(BatchRenderMode render_mode)
|
void GPU_HW_OpenGL_ES::SetDrawState(BatchRenderMode render_mode)
|
||||||
{
|
{
|
||||||
const GL::Program& prog = m_render_programs[static_cast<u8>(render_mode)][static_cast<u8>(m_batch.texture_mode)]
|
const GL::Program& prog = m_render_programs[static_cast<u8>(render_mode)][static_cast<u8>(m_batch.texture_mode)]
|
||||||
[BoolToUInt8(m_batch.dithering)];
|
[BoolToUInt8(m_batch.dithering)][BoolToUInt8(m_batch.interlacing)];
|
||||||
m_batch_ubo_dirty |= !prog.IsBound();
|
m_batch_ubo_dirty |= !prog.IsBound();
|
||||||
prog.Bind();
|
prog.Bind();
|
||||||
|
|
||||||
|
@ -311,6 +315,7 @@ void GPU_HW_OpenGL_ES::SetDrawState(BatchRenderMode render_mode)
|
||||||
prog.Uniform1f(2, m_batch_ubo_data.u_src_alpha_factor);
|
prog.Uniform1f(2, m_batch_ubo_data.u_src_alpha_factor);
|
||||||
prog.Uniform1f(3, m_batch_ubo_data.u_dst_alpha_factor);
|
prog.Uniform1f(3, m_batch_ubo_data.u_dst_alpha_factor);
|
||||||
prog.Uniform1i(4, static_cast<s32>(m_batch_ubo_data.u_set_mask_while_drawing));
|
prog.Uniform1i(4, static_cast<s32>(m_batch_ubo_data.u_set_mask_while_drawing));
|
||||||
|
prog.Uniform1i(5, static_cast<s32>(m_batch_ubo_data.u_interlaced_displayed_field));
|
||||||
m_batch_ubo_dirty = false;
|
m_batch_ubo_dirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,8 +385,7 @@ void GPU_HW_OpenGL_ES::UpdateDisplay()
|
||||||
const u32 scaled_flipped_vram_offset_y =
|
const u32 scaled_flipped_vram_offset_y =
|
||||||
m_vram_texture.GetHeight() - scaled_vram_offset_y - scaled_display_height;
|
m_vram_texture.GetHeight() - scaled_vram_offset_y - scaled_display_height;
|
||||||
|
|
||||||
const u32 reinterpret_field_offset =
|
const u32 reinterpret_field_offset = BoolToUInt32(m_GPUSTAT.displaying_odd_line);
|
||||||
(m_crtc_state.regs.Y + BoolToUInt8(interlaced && m_GPUSTAT.interlaced_field)) & 1u;
|
|
||||||
const u32 reinterpret_start_x = m_crtc_state.regs.X * m_resolution_scale;
|
const u32 reinterpret_start_x = m_crtc_state.regs.X * m_resolution_scale;
|
||||||
const u32 reinterpret_width = scaled_display_width + (m_crtc_state.display_vram_left - m_crtc_state.regs.X);
|
const u32 reinterpret_width = scaled_display_width + (m_crtc_state.display_vram_left - m_crtc_state.regs.X);
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common/gl/program.h"
|
#include "common/gl/program.h"
|
||||||
|
#include "common/gl/shader_cache.h"
|
||||||
#include "common/gl/stream_buffer.h"
|
#include "common/gl/stream_buffer.h"
|
||||||
#include "common/gl/texture.h"
|
#include "common/gl/texture.h"
|
||||||
#include "common/gl/shader_cache.h"
|
|
||||||
#include "glad.h"
|
#include "glad.h"
|
||||||
#include "gpu_hw.h"
|
#include "gpu_hw.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
@ -64,7 +64,8 @@ private:
|
||||||
|
|
||||||
std::vector<BatchVertex> m_vertex_buffer;
|
std::vector<BatchVertex> m_vertex_buffer;
|
||||||
|
|
||||||
std::array<std::array<std::array<GL::Program, 2>, 9>, 4> m_render_programs; // [render_mode][texture_mode][dithering]
|
std::array<std::array<std::array<std::array<GL::Program, 2>, 2>, 9>, 4>
|
||||||
std::array<std::array<GL::Program, 2>, 2> m_display_programs; // [depth_24][interlaced]
|
m_render_programs; // [render_mode][texture_mode][dithering][interlacing]
|
||||||
|
std::array<std::array<GL::Program, 2>, 2> m_display_programs; // [depth_24][interlaced]
|
||||||
GL::Program m_vram_read_program;
|
GL::Program m_vram_read_program;
|
||||||
};
|
};
|
||||||
|
|
|
@ -345,7 +345,8 @@ void GPU_HW_ShaderGen::DeclareFragmentEntryPoint(std::stringstream& ss, u32 num_
|
||||||
void GPU_HW_ShaderGen::WriteBatchUniformBuffer(std::stringstream& ss)
|
void GPU_HW_ShaderGen::WriteBatchUniformBuffer(std::stringstream& ss)
|
||||||
{
|
{
|
||||||
DeclareUniformBuffer(ss, {"uint2 u_texture_window_mask", "uint2 u_texture_window_offset", "float u_src_alpha_factor",
|
DeclareUniformBuffer(ss, {"uint2 u_texture_window_mask", "uint2 u_texture_window_offset", "float u_src_alpha_factor",
|
||||||
"float u_dst_alpha_factor", "bool u_set_mask_while_drawing"});
|
"float u_dst_alpha_factor", "bool u_set_mask_while_drawing",
|
||||||
|
"int u_interlaced_displayed_field"});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured)
|
std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured)
|
||||||
|
@ -394,7 +395,8 @@ std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMode transparency,
|
std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMode transparency,
|
||||||
GPU::TextureMode texture_mode, bool dithering)
|
GPU::TextureMode texture_mode, bool dithering,
|
||||||
|
bool interlacing)
|
||||||
{
|
{
|
||||||
const GPU::TextureMode actual_texture_mode = texture_mode & ~GPU::TextureMode::RawTextureBit;
|
const GPU::TextureMode actual_texture_mode = texture_mode & ~GPU::TextureMode::RawTextureBit;
|
||||||
const bool raw_texture = (texture_mode & GPU::TextureMode::RawTextureBit) == GPU::TextureMode::RawTextureBit;
|
const bool raw_texture = (texture_mode & GPU::TextureMode::RawTextureBit) == GPU::TextureMode::RawTextureBit;
|
||||||
|
@ -416,6 +418,7 @@ std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMod
|
||||||
DefineMacro(ss, "RAW_TEXTURE", raw_texture);
|
DefineMacro(ss, "RAW_TEXTURE", raw_texture);
|
||||||
DefineMacro(ss, "DITHERING", dithering);
|
DefineMacro(ss, "DITHERING", dithering);
|
||||||
DefineMacro(ss, "DITHERING_SCALED", m_scaled_dithering);
|
DefineMacro(ss, "DITHERING_SCALED", m_scaled_dithering);
|
||||||
|
DefineMacro(ss, "INTERLACING", interlacing);
|
||||||
DefineMacro(ss, "TRUE_COLOR", m_true_color);
|
DefineMacro(ss, "TRUE_COLOR", m_true_color);
|
||||||
DefineMacro(ss, "TEXTURE_FILTERING", m_texture_filering);
|
DefineMacro(ss, "TEXTURE_FILTERING", m_texture_filering);
|
||||||
DefineMacro(ss, "USE_DUAL_SOURCE", use_dual_source);
|
DefineMacro(ss, "USE_DUAL_SOURCE", use_dual_source);
|
||||||
|
@ -519,6 +522,11 @@ float4 SampleFromVRAM(int4 texpage, int2 icoord)
|
||||||
float ialpha;
|
float ialpha;
|
||||||
float oalpha;
|
float oalpha;
|
||||||
|
|
||||||
|
#if INTERLACING
|
||||||
|
if (((int(v_pos.y) / RESOLUTION_SCALE) & 1) == u_interlaced_displayed_field)
|
||||||
|
discard;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if TEXTURED
|
#if TEXTURED
|
||||||
#if TEXTURE_FILTERING
|
#if TEXTURE_FILTERING
|
||||||
int2 icoord = int2(v_tex0);
|
int2 icoord = int2(v_tex0);
|
||||||
|
|
|
@ -13,7 +13,7 @@ public:
|
||||||
|
|
||||||
std::string GenerateBatchVertexShader(bool textured);
|
std::string GenerateBatchVertexShader(bool textured);
|
||||||
std::string GenerateBatchFragmentShader(GPU_HW::BatchRenderMode transparency, GPU::TextureMode texture_mode,
|
std::string GenerateBatchFragmentShader(GPU_HW::BatchRenderMode transparency, GPU::TextureMode texture_mode,
|
||||||
bool dithering);
|
bool dithering, bool interlacing);
|
||||||
std::string GenerateBatchLineExpandGeometryShader();
|
std::string GenerateBatchLineExpandGeometryShader();
|
||||||
std::string GenerateScreenQuadVertexShader();
|
std::string GenerateScreenQuadVertexShader();
|
||||||
std::string GenerateFillFragmentShader();
|
std::string GenerateFillFragmentShader();
|
||||||
|
|
|
@ -574,8 +574,11 @@ void GPU_SW::ShadePixel(u32 x, u32 y, u8 color_r, u8 color_g, u8 color_b, u8 tex
|
||||||
if ((bg_color.bits & mask_and) != 0)
|
if ((bg_color.bits & mask_and) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_GPUSTAT.SkipDrawingToActiveField() && BoolToUInt32(m_GPUSTAT.drawing_even_line) != (static_cast<u32>(y) & 1u))
|
if (m_GPUSTAT.SkipDrawingToActiveField() &&
|
||||||
|
BoolToUInt32(m_GPUSTAT.displaying_odd_line) == (static_cast<u32>(y) & 1u))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SetPixel(static_cast<u32>(x), static_cast<u32>(y), color.bits | m_GPUSTAT.GetMaskOR());
|
SetPixel(static_cast<u32>(x), static_cast<u32>(y), color.bits | m_GPUSTAT.GetMaskOR());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue