Skip to content

Commit

Permalink
gl/vk: Bug fixes and improvements (#2155)
Browse files Browse the repository at this point in the history
* gl: Fix broken buffer reserve computation

* gl: Texture format fixes

* gl: Two sided lighting

* gl: Always update glsl output registers

* gl: Simplify vertex input declaration

* vk: Always write output registers

* vk/gl: swizzle component read on depth textures

* gl/vk: Use proper MVP matrix

gl: fix broken mvp when window_origin=top

* vk/gl: Move fragment operations block into the proxy function
  • Loading branch information
kd-11 authored and raven02 committed Sep 26, 2016
1 parent 38f35df commit 7884356
Show file tree
Hide file tree
Showing 11 changed files with 421 additions and 111 deletions.
170 changes: 147 additions & 23 deletions rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp
@@ -1,4 +1,5 @@
#include "stdafx.h"
#include <set>
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "GLFragmentProgram.h"
Expand Down Expand Up @@ -42,15 +43,43 @@ void GLFragmentDecompilerThread::insertHeader(std::stringstream & OS)

void GLFragmentDecompilerThread::insertIntputs(std::stringstream & OS)
{
bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output);

for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
{
for (const ParamItem& PI : PT.items)
{
//Rename fogc to fog_c to differentiate the input register from the variable
if (PI.name == "fogc")
OS << "in vec4 fog_c;" << std::endl;

OS << "in " << PT.type << " " << PI.name << ";" << std::endl;
//ssa is defined in the program body and is not a varying type
if (PI.name == "ssa") continue;

std::string var_name = PI.name;

if (two_sided_enabled)
{
if (m_prog.back_color_diffuse_output && var_name == "diff_color")
var_name = "back_diff_color";

if (m_prog.back_color_specular_output && var_name == "spec_color")
var_name = "back_spec_color";
}

if (var_name == "fogc")
var_name = "fog_c";

OS << "in " << PT.type << " " << var_name << ";" << std::endl;
}
}

if (two_sided_enabled)
{
if (m_prog.front_color_diffuse_output && m_prog.back_color_diffuse_output)
{
OS << "in vec4 front_diff_color;" << std::endl;
}

if (m_prog.front_color_specular_output && m_prog.back_color_specular_output)
{
OS << "in vec4 front_spec_color;" << std::endl;
}
}
}
Expand Down Expand Up @@ -184,16 +213,38 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
{
insert_glsl_legacy_function(OS);

OS << "void main ()" << std::endl;
const std::set<std::string> output_values =
{
"r0", "r1", "r2", "r3", "r4",
"h0", "h2", "h4", "h6", "h8"
};

std::string parameters = "";
for (auto &reg_name : output_values)
{
if (m_parr.HasParam(PF_PARAM_NONE, "vec4", reg_name))
{
if (parameters.length())
parameters += ", ";

parameters += "inout vec4 " + reg_name;
}
}

OS << "void fs_main(" << parameters << ")" << std::endl;
OS << "{" << std::endl;

for (const ParamType& PT : m_parr.params[PF_PARAM_NONE])
{
for (const ParamItem& PI : PT.items)
{
if (output_values.find(PI.name) != output_values.end())
continue;

OS << " " << PT.type << " " << PI.name;
if (!PI.value.empty())
OS << " = " << PI.value;

OS << ";" << std::endl;
}
}
Expand All @@ -214,11 +265,49 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
}
}

// search if there is fogc in inputs
bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output);

for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
{
for (const ParamItem& PI : PT.items)
{
if (two_sided_enabled)
{
if (PI.name == "spec_color")
{
if (m_prog.back_color_specular_output)
{
if (m_prog.back_color_specular_output && m_prog.front_color_specular_output)
{
OS << " vec4 spec_color = gl_FrontFacing ? front_spec_color : back_spec_color;\n";
}
else
{
OS << " vec4 spec_color = back_spec_color;\n";
}
}

continue;
}

else if (PI.name == "diff_color")
{
if (m_prog.back_color_diffuse_output)
{
if (m_prog.back_color_diffuse_output && m_prog.front_color_diffuse_output)
{
OS << " vec4 diff_color = gl_FrontFacing ? front_diff_color : back_diff_color;\n";
}
else
{
OS << " vec4 diff_color = back_diff_color;\n";
}
}

continue;
}
}

if (PI.name == "fogc")
{
insert_fog_declaration(OS, m_prog.fog_equation);
Expand All @@ -238,25 +327,21 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS)
{ "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" },
};

std::string first_output_name;
for (int i = 0; i < sizeof(table) / sizeof(*table); ++i)
const std::set<std::string> output_values =
{
if (m_parr.HasParam(PF_PARAM_NONE, "vec4", table[i].second))
{
OS << " " << table[i].first << " = " << table[i].second << ";" << std::endl;
if (first_output_name.empty()) first_output_name = table[i].first;
}
}
"r0", "r1", "r2", "r3", "r4",
"h0", "h2", "h4", "h6", "h8"
};

if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT)
std::string first_output_name = "";
std::string color_output_block = "";

for (int i = 0; i < sizeof(table) / sizeof(*table); ++i)
{
if (m_parr.HasParam(PF_PARAM_NONE, "vec4", table[i].second))
{
/** Note: Naruto Shippuden : Ultimate Ninja Storm 2 sets CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS in a shader
* but it writes depth in r1.z and not h2.z.
* Maybe there's a different flag for depth ?
*/
//OS << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "\tgl_FragDepth = r1.z;\n" : "\tgl_FragDepth = h0.z;\n") << std::endl;
OS << " gl_FragDepth = r1.z;\n";
color_output_block += " " + table[i].first + " = " + table[i].second + ";\n";
if (first_output_name.empty()) first_output_name = table[i].second;
}
}

Expand Down Expand Up @@ -294,6 +379,41 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS)
OS << make_comparison_test(m_prog.alpha_func, "alpha_test != 0 && ", first_output_name + ".a", "alpha_ref");
}

OS << "}" << std::endl << std::endl;

OS << "void main()" << std::endl;
OS << "{" << std::endl;

std::string parameters = "";
for (auto &reg_name : output_values)
{
if (m_parr.HasParam(PF_PARAM_NONE, "vec4", reg_name))
{
if (parameters.length())
parameters += ", ";

parameters += reg_name;
OS << " vec4 " << reg_name << " = vec4(0.);" << std::endl;
}
}

OS << std::endl << " fs_main(" + parameters + ");" << std::endl << std::endl;

//Append the color output assignments
OS << color_output_block;

if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT)
{
{
/** Note: Naruto Shippuden : Ultimate Ninja Storm 2 sets CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS in a shader
* but it writes depth in r1.z and not h2.z.
* Maybe there's a different flag for depth ?
*/
//OS << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "\tgl_FragDepth = r1.z;\n" : "\tgl_FragDepth = h0.z;\n") << std::endl;
OS << " gl_FragDepth = r1.z;\n";
}
}

OS << "}" << std::endl;
}

Expand All @@ -320,8 +440,12 @@ void GLFragmentProgram::Decompile(const RSXFragmentProgram& prog)
{
for (const ParamItem& PI : PT.items)
{
if (PT.type == "sampler2D")
if (PT.type == "sampler1D" ||
PT.type == "sampler2D" ||
PT.type == "sampler3D" ||
PT.type == "samplerCube")
continue;

size_t offset = atoi(PI.name.c_str() + 2);
FragmentConstantOffsetCache.push_back(offset);
}
Expand Down
24 changes: 5 additions & 19 deletions rpcs3/Emu/RSX/GL/GLGSRender.cpp
Expand Up @@ -477,31 +477,17 @@ void GLGSRender::end()

void GLGSRender::set_viewport()
{
u16 viewport_x = rsx::method_registers.viewport_origin_x();
u16 viewport_y = rsx::method_registers.viewport_origin_y();
u16 viewport_w = rsx::method_registers.viewport_width();
u16 viewport_h = rsx::method_registers.viewport_height();
//NOTE: scale offset matrix already contains the viewport transformation
glViewport(0, 0, rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height());

u16 scissor_x = rsx::method_registers.scissor_origin_x();
u16 scissor_w = rsx::method_registers.scissor_width();
u16 scissor_y = rsx::method_registers.scissor_origin_y();
u16 scissor_h = rsx::method_registers.scissor_height();

rsx::window_origin shader_window_origin = rsx::method_registers.shader_window_origin();

if (shader_window_origin == rsx::window_origin::bottom)
{
__glcheck glViewport(viewport_x, viewport_y, viewport_w, viewport_h);
__glcheck glScissor(scissor_x, scissor_y, scissor_w, scissor_h);
}
else
{
u16 shader_window_height = rsx::method_registers.shader_window_height();

__glcheck glViewport(viewport_x, shader_window_height - viewport_y - viewport_h + 1, viewport_w, viewport_h);
__glcheck glScissor(scissor_x, shader_window_height - scissor_y - scissor_h + 1, scissor_w, scissor_h);
}

//NOTE: window origin does not affect scissor region (probably only affects viewport matrix; already applied)
//See LIMBO [NPUB-30373] which uses shader window origin = top
__glcheck glScissor(scissor_x, scissor_y, scissor_w, scissor_h);
glEnable(GL_SCISSOR_TEST);
}

Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/RSX/GL/GLRenderTargets.h
Expand Up @@ -122,6 +122,7 @@ struct gl_render_target_traits
.type(format.type)
.format(format.format)
.internal_format(format.internal_format)
.swizzle(gl::texture::channel::r, gl::texture::channel::r, gl::texture::channel::r, gl::texture::channel::r)
.wrap(gl::texture::wrap::clamp_to_border, gl::texture::wrap::clamp_to_border, gl::texture::wrap::clamp_to_border)
.apply();

Expand Down
45 changes: 16 additions & 29 deletions rpcs3/Emu/RSX/GL/GLTexture.cpp
Expand Up @@ -128,6 +128,7 @@ namespace
case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_R6G5B5:
case CELL_GCM_TEXTURE_R5G6B5:
//case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_A8R8G8B8: // TODO
case CELL_GCM_TEXTURE_DEPTH24_D8:
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
Expand All @@ -140,24 +141,20 @@ namespace
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
return { GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE };

case CELL_GCM_TEXTURE_B8:
return { GL_RED, GL_RED, GL_RED, GL_RED };
case CELL_GCM_TEXTURE_A4R4G4B4:
return{ GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA };

case CELL_GCM_TEXTURE_A4R4G4B4:
return { GL_BLUE, GL_ALPHA, GL_RED, GL_GREEN };
case CELL_GCM_TEXTURE_B8:
case CELL_GCM_TEXTURE_X16:
case CELL_GCM_TEXTURE_X32_FLOAT:
return { GL_RED, GL_RED, GL_RED, GL_RED };

case CELL_GCM_TEXTURE_G8B8:
return { GL_GREEN, GL_RED, GL_GREEN, GL_RED};

case CELL_GCM_TEXTURE_X16:
return { GL_RED, GL_RED, GL_RED, GL_RED };

case CELL_GCM_TEXTURE_Y16_X16:
return { GL_RED, GL_GREEN, GL_RED, GL_GREEN};

case CELL_GCM_TEXTURE_X32_FLOAT:
return { GL_RED, GL_RED, GL_RED, GL_RED };

case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
return { GL_GREEN, GL_RED, GL_GREEN, GL_RED };

Expand Down Expand Up @@ -492,25 +489,15 @@ namespace rsx

glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, tex.get_exact_mipmap_count() - 1);

if (format != CELL_GCM_TEXTURE_B8 && format != CELL_GCM_TEXTURE_X16 && format != CELL_GCM_TEXTURE_X32_FLOAT)
{
u8 remap_a = tex.remap() & 0x3;
u8 remap_r = (tex.remap() >> 2) & 0x3;
u8 remap_g = (tex.remap() >> 4) & 0x3;
u8 remap_b = (tex.remap() >> 6) & 0x3;

__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]);
}
else
{
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[0]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[1]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[2]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[3]);
}
u8 remap_a = tex.remap() & 0x3;
u8 remap_r = (tex.remap() >> 2) & 0x3;
u8 remap_g = (tex.remap() >> 4) & 0x3;
u8 remap_b = (tex.remap() >> 6) & 0x3;

__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]);

__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_S, gl_wrap(tex.wrap_s()));
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_T, gl_wrap(tex.wrap_t()));
Expand Down
1 change: 0 additions & 1 deletion rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp
Expand Up @@ -351,7 +351,6 @@ namespace
const rsx::draw_indexed_array_command& command)
{
u32 min_index = 0, max_index = 0;
u32 max_vertex_attrib_size = 0;

rsx::index_array_type type = rsx::method_registers.index_type();
u32 type_size = ::narrow<u32>(get_index_type_size(type));
Expand Down

1 comment on commit 7884356

@fenix008
Copy link

@fenix008 fenix008 commented on 7884356 Sep 26, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

woohoo, with your commit appear some improve in VF5:FS ! (about textures sure!)
https://puu.sh/rkkdS/fc2f81e002.jpg (old)
http://puu.sh/rooMx/dc10d5ebd5.jpg (now)

Update: Screenshot from OpenGL - https://puu.sh/rorKb/b3d46d2200.jpg (looks better than Vulkan now)

Please sign in to comment.