GPU: Implement texture window

This commit is contained in:
Connor McLaughlin 2019-10-05 23:25:06 +10:00
parent f59d35023c
commit bc8e035e37
5 changed files with 59 additions and 6 deletions

View File

@ -73,9 +73,11 @@ bool GPU::DoState(StateWrapper& sw)
sw.Do(&m_render_state.texture_y_flip);
sw.Do(&m_render_state.texpage_attribute);
sw.Do(&m_render_state.texlut_attribute);
sw.Do(&m_render_state.texture_window_value);
sw.Do(&m_render_state.texture_page_changed);
sw.Do(&m_render_state.texture_color_mode_changed);
sw.Do(&m_render_state.transparency_mode_changed);
sw.Do(&m_render_state.texture_window_changed);
sw.Do(&m_drawing_area.left);
sw.Do(&m_drawing_area.top);
@ -113,6 +115,7 @@ bool GPU::DoState(StateWrapper& sw)
m_render_state.texture_page_changed = true;
m_render_state.texture_color_mode_changed = true;
m_render_state.transparency_mode_changed = true;
m_render_state.texture_window_changed = true;
UpdateGPUSTAT();
}
@ -437,10 +440,7 @@ void GPU::WriteGP0(u32 value)
case 0xE2: // set texture window
{
m_render_state.texture_window_mask_x = param & UINT32_C(0x1F);
m_render_state.texture_window_mask_y = (param >> 5) & UINT32_C(0x1F);
m_render_state.texture_window_offset_x = (param >> 10) & UINT32_C(0x1F);
m_render_state.texture_window_offset_y = (param >> 15) & UINT32_C(0x1F);
m_render_state.SetTextureWindow(value);
Log_DebugPrintf("Set texture window %02X %02X %02X %02X", m_render_state.texture_window_mask_x,
m_render_state.texture_window_mask_y, m_render_state.texture_window_offset_x,
m_render_state.texture_window_offset_y);
@ -895,6 +895,20 @@ void GPU::RenderState::SetFromPaletteAttribute(u16 value)
texture_page_changed = true;
}
void GPU::RenderState::SetTextureWindow(u32 value)
{
value &= TEXTURE_WINDOW_MASK;
if (texture_window_value == value)
return;
texture_window_mask_x = value & UINT32_C(0x1F);
texture_window_mask_y = (value >> 5) & UINT32_C(0x1F);
texture_window_offset_x = (value >> 10) & UINT32_C(0x1F);
texture_window_offset_y = (value >> 15) & UINT32_C(0x1F);
texture_window_value = value;
texture_window_changed = true;
}
bool GPU::DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride, const void* buffer, bool remove_alpha)
{
std::vector<u32> rgba8_buf(width * height);

View File

@ -240,6 +240,7 @@ protected:
static constexpr u16 PAGE_ATTRIBUTE_TEXTURE_PAGE_MASK = UINT16_C(0b0000000000011111);
static constexpr u16 PAGE_ATTRIBUTE_MASK = UINT16_C(0b0000000111111111);
static constexpr u16 PALETTE_ATTRIBUTE_MASK = UINT16_C(0b0111111111111111);
static constexpr u32 TEXTURE_WINDOW_MASK = UINT16_C(0b11111111111111111111);
// decoded values
u32 texture_page_x;
@ -258,10 +259,12 @@ protected:
// original values
u16 texpage_attribute; // from register in rectangle modes/vertex in polygon modes
u16 texlut_attribute; // from vertex
u32 texture_window_value;
bool texture_page_changed = false;
bool texture_color_mode_changed = false;
bool transparency_mode_changed = false;
bool texture_window_changed = false;
bool IsChanged() const { return texture_page_changed || texture_color_mode_changed || transparency_mode_changed; }
@ -274,11 +277,15 @@ protected:
bool IsTransparencyModeChanged() const { return transparency_mode_changed; }
void ClearTransparencyModeChangedFlag() { transparency_mode_changed = false; }
bool IsTextureWindowChanged() const { return texture_window_changed; }
void ClearTextureWindowChangedFlag() { texture_window_changed = false; }
void SetFromPolygonTexcoord(u32 texcoord0, u32 texcoord1);
void SetFromRectangleTexcoord(u32 texcoord);
void SetFromPageAttribute(u16 value);
void SetFromPaletteAttribute(u16 value);
void SetTextureWindow(u32 value);
} m_render_state = {};
struct DrawingArea

View File

@ -46,9 +46,17 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices)
hw_vert.texpage = texpage;
if (textured)
{
hw_vert.texcoord = Truncate16(m_GP0_command[buffer_pos++]);
// auto [u, v] = HWVertex::DecodeTexcoord(hw_vert.texcoord);
// u = (u & (~(m_render_state.texture_window_mask_x * 8))) | ((m_render_state.texture_window_offset_x &
// m_render_state.texture_window_mask_x) * 8); v = (v & (~(m_render_state.texture_window_mask_y * 8))) |
// ((m_render_state.texture_window_offset_y & m_render_state.texture_window_mask_y) * 8);
}
else
{
hw_vert.texcoord = 0;
}
hw_vert.padding = 0;
@ -258,15 +266,24 @@ uniform vec2 u_transparent_alpha;
in vec2 v_tex0;
flat in ivec4 v_texpage;
uniform sampler2D samp0;
uniform uvec4 u_texture_window;
#endif
out vec4 o_col0;
#if TEXTURED
ivec2 ApplyTextureWindow(ivec2 coords)
{
uint x = (uint(coords.x) & ~(u_texture_window.x * 8u)) | ((u_texture_window.z & u_texture_window.x) * 8u);
uint y = (uint(coords.y) & ~(u_texture_window.y * 8u)) | ((u_texture_window.w & u_texture_window.y) * 8u);
return ivec2(int(x), int(y));
}
vec4 SampleFromVRAM(vec2 coord)
{
// from 0..1 to 0..255
ivec2 icoord = ivec2(coord * vec2(255.0));
icoord = ApplyTextureWindow(icoord);
// adjust for tightly packed palette formats
ivec2 index_coord = icoord;
@ -493,7 +510,7 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)
const bool restart_line_strip = (rc_primitive == HWRenderBatch::Primitive::LineStrip);
const bool needs_flush =
!IsFlushed() && (m_render_state.IsTextureColorModeChanged() || m_render_state.IsTransparencyModeChanged() ||
buffer_overflow || rc_changed || restart_line_strip);
m_render_state.IsTextureWindowChanged() || buffer_overflow || rc_changed || restart_line_strip);
if (needs_flush)
FlushRender();
@ -544,5 +561,14 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)
m_render_state.ClearTransparencyModeChangedFlag();
}
if (m_render_state.IsTextureWindowChanged())
{
m_batch.texture_window_values[0] = m_render_state.texture_window_mask_x;
m_batch.texture_window_values[1] = m_render_state.texture_window_mask_y;
m_batch.texture_window_values[2] = m_render_state.texture_window_offset_x;
m_batch.texture_window_values[3] = m_render_state.texture_window_offset_y;
m_render_state.ClearTextureWindowChangedFlag();
}
LoadVertices(rc, num_vertices);
}

View File

@ -51,6 +51,7 @@ protected:
u32 texture_palette_x;
u32 texture_palette_y;
TransparencyMode transparency_mode;
std::array<u8, 4> texture_window_values;
std::vector<HWVertex> vertices;
};

View File

@ -358,8 +358,9 @@ bool GPU_HW_OpenGL::CompileProgram(GL::Program& prog, bool transparent, bool tex
if (textured)
{
prog.RegisterUniform("u_texture_window");
prog.RegisterUniform("samp0");
prog.Uniform1i(2, 0);
prog.Uniform1i(3, 0);
}
return true;
@ -385,7 +386,11 @@ void GPU_HW_OpenGL::SetDrawState()
}
if (m_batch.texture_enable)
{
prog.Uniform4ui(2, m_batch.texture_window_values[0], m_batch.texture_window_values[1],
m_batch.texture_window_values[2], m_batch.texture_window_values[3]);
m_vram_read_texture->Bind();
}
if (m_last_transparency_enable != m_batch.transparency_enable ||
(m_last_transparency_enable && m_last_transparency_mode != m_batch.transparency_mode))