mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
rsx/gl: Implement resolution scaling
rsx: Revise wpos calculation to take resolution scale into account
This commit is contained in:
parent
47202d5839
commit
12ab03b0b5
@ -731,9 +731,9 @@ struct area_base
|
||||
{
|
||||
return{ x1 * size.width, y1 * size.height, x2 * size.width, y2 * size.height };
|
||||
}
|
||||
constexpr area_base operator * (const T& value) const
|
||||
constexpr area_base operator * (const f32& value) const
|
||||
{
|
||||
return{ x1 * value, y1 * value, x2 * value, y2 * value };
|
||||
return{ (T)(x1 * value), (T)(y1 * value), (T)(x2 * value), (T)(y2 * value) };
|
||||
}
|
||||
|
||||
template<typename NT>
|
||||
|
@ -338,6 +338,12 @@ namespace glsl
|
||||
OS << "{\n";
|
||||
OS << " return decodeLinearDepth(texture(tex, coord.xy).r);\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
OS << "vec4 get_wpos()\n";
|
||||
OS << "{\n";
|
||||
OS << " float abs_scale = abs(wpos_scale);\n";
|
||||
OS << " return (gl_FragCoord * vec4(abs_scale, wpos_scale, 1., 1.)) + vec4(0., wpos_bias, 0., 0.);\n";
|
||||
OS << "}\n\n";
|
||||
}
|
||||
|
||||
static void insert_fog_declaration(std::ostream& OS)
|
||||
|
@ -167,6 +167,9 @@ public:
|
||||
f32 fp_value;
|
||||
};
|
||||
|
||||
program_buffer_patch_entry()
|
||||
{}
|
||||
|
||||
program_buffer_patch_entry(f32& key, f32& value)
|
||||
{
|
||||
fp_key = key;
|
||||
@ -178,25 +181,43 @@ public:
|
||||
hex_key = key;
|
||||
hex_value = value;
|
||||
}
|
||||
|
||||
bool test_and_set(f32 value, f32* dst) const
|
||||
{
|
||||
u32 hex = (u32&)value;
|
||||
if ((hex & 0x7FFFFFFF) == (hex_key & 0x7FFFFFFF))
|
||||
{
|
||||
hex = (hex & ~0x7FFFFFF) | hex_value;
|
||||
*dst = (f32&)hex;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
std::vector<program_buffer_patch_entry> keys;
|
||||
std::unordered_map<f32, program_buffer_patch_entry> db;
|
||||
|
||||
void add(program_buffer_patch_entry& e)
|
||||
{
|
||||
keys.push_back(e);
|
||||
db[e.fp_key] = e;
|
||||
}
|
||||
|
||||
void add(f32& key, f32& value)
|
||||
{
|
||||
db[key] = { key, value };
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
keys.resize(0);
|
||||
db.clear();
|
||||
}
|
||||
|
||||
bool is_empty() const
|
||||
{
|
||||
return keys.size() == 0;
|
||||
return db.size() == 0;
|
||||
}
|
||||
}
|
||||
patch_table;
|
||||
@ -287,49 +308,43 @@ public:
|
||||
|
||||
verify(HERE), (dst_buffer.size_bytes() >= ::narrow<int>(I->second.FragmentConstantOffsetCache.size()) * 16);
|
||||
|
||||
size_t offset = 0;
|
||||
if (patch_table.is_empty())
|
||||
{
|
||||
f32* dst = dst_buffer.data();
|
||||
f32 tmp[4];
|
||||
for (size_t offset_in_fragment_program : I->second.FragmentConstantOffsetCache)
|
||||
{
|
||||
void *data = (char*)fragment_program.addr + (u32)offset_in_fragment_program;
|
||||
const __m128i &vector = _mm_loadu_si128((__m128i*)data);
|
||||
const __m128i &shuffled_vector = _mm_shuffle_epi8(vector, mask);
|
||||
_mm_stream_si128((__m128i*)dst_buffer.subspan(offset, 4).data(), shuffled_vector);
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (!patch_table.is_empty())
|
||||
{
|
||||
for (size_t offset_in_fragment_program : I->second.FragmentConstantOffsetCache)
|
||||
{
|
||||
void *data = (char*)fragment_program.addr + (u32)offset_in_fragment_program;
|
||||
f32* src = (f32*)data;
|
||||
f32* dst = dst_buffer.subspan(offset, 4).data();
|
||||
_mm_storeu_ps(tmp, (__m128&)shuffled_vector);
|
||||
bool patched;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
patched = false;
|
||||
for (auto& e : patch_table.keys)
|
||||
for (auto& e : patch_table.db)
|
||||
{
|
||||
//TODO: Use fp comparison with fabsf without hurting performance
|
||||
if (e.hex_key == (u32&)src[i])
|
||||
if (patched = e.second.test_and_set(tmp[i], &dst[i]))
|
||||
{
|
||||
dst[i] = e.fp_value;
|
||||
patched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!patched)
|
||||
{
|
||||
dst[i] = src[i];
|
||||
dst[i] = tmp[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_mm_stream_si128((__m128i*)dst, shuffled_vector);
|
||||
}
|
||||
|
||||
offset += 4;
|
||||
}
|
||||
dst += 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -856,13 +856,14 @@ namespace rsx
|
||||
|
||||
return rsc.surface->get_view();
|
||||
}
|
||||
else
|
||||
return create_temporary_subresource_view(cmd, rsc.surface, format, rsc.x, rsc.y, rsc.w, rsc.h);
|
||||
else return create_temporary_subresource_view(cmd, rsc.surface, format, rsx::apply_resolution_scale(rsc.x, false), rsx::apply_resolution_scale(rsc.y, false),
|
||||
rsx::apply_resolution_scale(rsc.w, true), rsx::apply_resolution_scale(rsc.h, true));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr);
|
||||
return create_temporary_subresource_view(cmd, rsc.surface, format, rsc.x, rsc.y, rsc.w, rsc.h);
|
||||
return create_temporary_subresource_view(cmd, rsc.surface, format, rsx::apply_resolution_scale(rsc.x, false), rsx::apply_resolution_scale(rsc.y, false),
|
||||
rsx::apply_resolution_scale(rsc.w, true), rsx::apply_resolution_scale(rsc.h, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1198,6 +1199,13 @@ namespace rsx
|
||||
default_remap_vector)->get_raw_texture();
|
||||
}
|
||||
|
||||
const f32 scale = rsx::get_resolution_scale();
|
||||
if (src_is_render_target)
|
||||
src_area = src_area * scale;
|
||||
|
||||
if (dst_is_render_target)
|
||||
dst_area = dst_area * scale;
|
||||
|
||||
blitter.scale_image(vram_texture, dest_texture, src_area, dst_area, interpolate, is_depth_blit);
|
||||
return true;
|
||||
}
|
||||
|
@ -46,8 +46,8 @@ void D3D12FragmentDecompiler::insertHeader(std::stringstream & OS)
|
||||
OS << " float alpha_ref;\n";
|
||||
OS << " uint alpha_func;\n";
|
||||
OS << " uint fog_mode;\n";
|
||||
OS << " uint window_origin;\n";
|
||||
OS << " uint window_height;\n";
|
||||
OS << " float wpos_scale;\n";
|
||||
OS << " float wpos_bias;\n";
|
||||
OS << " float4 texture_parameters[16];\n";
|
||||
OS << "};\n";
|
||||
}
|
||||
@ -224,8 +224,10 @@ void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS)
|
||||
}
|
||||
}
|
||||
|
||||
//NOTE: Framebuffer scaling not actually supported. wpos_scale is used to reconstruct the true window height
|
||||
OS << " float4 wpos = In.Position;\n";
|
||||
OS << " if (window_origin != 0) wpos.y = window_height - wpos.y;\n";
|
||||
OS << " float4 res_scale = abs(1.f / wpos_scale);\n";
|
||||
OS << " if (wpos_scale < 0) wpos.y = (wpos_bias * res_scale) - wpos.y;\n";
|
||||
OS << " float4 ssa = is_front_face ? float4(1., 1., 1., 1.) : float4(-1., -1., -1., -1.);\n";
|
||||
|
||||
// Declare output
|
||||
|
@ -154,8 +154,8 @@ void GLFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
||||
OS << " float alpha_ref;\n";
|
||||
OS << " uint alpha_func;\n";
|
||||
OS << " uint fog_mode;\n";
|
||||
OS << " uint window_origin;\n";
|
||||
OS << " uint window_height;\n";
|
||||
OS << " float wpos_scale;\n";
|
||||
OS << " float wpos_bias;\n";
|
||||
OS << " vec4 texture_parameters[16];\n"; //sampling: x,y scaling and (unused) offsets data
|
||||
OS << "};\n";
|
||||
}
|
||||
@ -251,8 +251,7 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
|
||||
}
|
||||
|
||||
OS << " vec4 ssa = gl_FrontFacing ? vec4(1.) : vec4(-1.);\n";
|
||||
OS << " vec4 wpos = gl_FragCoord;\n";
|
||||
OS << " if (window_origin != 0) wpos.y = window_height - wpos.y;\n";
|
||||
OS << " vec4 wpos = get_wpos();\n";
|
||||
|
||||
for (const ParamType& PT : m_parr.params[PF_PARAM_UNIFORM])
|
||||
{
|
||||
|
@ -589,14 +589,14 @@ void GLGSRender::end()
|
||||
void GLGSRender::set_viewport()
|
||||
{
|
||||
//NOTE: scale offset matrix already contains the viewport transformation
|
||||
const auto clip_width = rsx::method_registers.surface_clip_width();
|
||||
const auto clip_height = rsx::method_registers.surface_clip_height();
|
||||
const auto clip_width = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_width(), true);
|
||||
const auto clip_height = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_height(), true);
|
||||
glViewport(0, 0, clip_width, 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();
|
||||
u16 scissor_x = rsx::apply_resolution_scale(rsx::method_registers.scissor_origin_x(), false);
|
||||
u16 scissor_w = rsx::apply_resolution_scale(rsx::method_registers.scissor_width(), true);
|
||||
u16 scissor_y = rsx::apply_resolution_scale(rsx::method_registers.scissor_origin_y(), false);
|
||||
u16 scissor_h = rsx::apply_resolution_scale(rsx::method_registers.scissor_height(), true);
|
||||
|
||||
//Do not bother drawing anything if output is zero sized
|
||||
//TODO: Clip scissor region
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "GLHelpers.h"
|
||||
#include "stdafx.h"
|
||||
#include "../RSXThread.h"
|
||||
#include "../rsx_utils.h"
|
||||
|
||||
struct color_swizzle
|
||||
{
|
||||
@ -55,6 +56,8 @@ namespace gl
|
||||
u32 rsx_pitch = 0;
|
||||
u16 native_pitch = 0;
|
||||
|
||||
u16 internal_width = 0;
|
||||
u16 internal_height = 0;
|
||||
u16 surface_height = 0;
|
||||
u16 surface_width = 0;
|
||||
u16 surface_pixel_size = 0;
|
||||
@ -130,8 +133,16 @@ namespace gl
|
||||
|
||||
void update_surface()
|
||||
{
|
||||
surface_width = width();
|
||||
surface_height = height();
|
||||
internal_width = width();
|
||||
internal_height = height();
|
||||
surface_width = rsx::apply_inverse_resolution_scale(internal_width, true);
|
||||
surface_height = rsx::apply_inverse_resolution_scale(internal_height, true);
|
||||
}
|
||||
|
||||
bool matches_dimensions(u16 _width, u16 _height) const
|
||||
{
|
||||
//Use foward scaling to account for rounding and clamping errors
|
||||
return (rsx::apply_resolution_scale(_width, true) == internal_width) && (rsx::apply_resolution_scale(_height, true) == internal_height);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -162,7 +173,7 @@ struct gl_render_target_traits
|
||||
result->set_compatible_format(internal_fmt);
|
||||
|
||||
__glcheck result->config()
|
||||
.size({ (int)width, (int)height })
|
||||
.size({ (int)rsx::apply_resolution_scale((u16)width, true), (int)rsx::apply_resolution_scale((u16)height, true) })
|
||||
.type(format.type)
|
||||
.format(format.format)
|
||||
.internal_format(internal_fmt)
|
||||
@ -195,8 +206,10 @@ struct gl_render_target_traits
|
||||
auto format = rsx::internals::surface_depth_format_to_gl(surface_depth_format);
|
||||
result->recreate(gl::texture::target::texture2D);
|
||||
|
||||
const auto scale = rsx::get_resolution_scale();
|
||||
|
||||
__glcheck result->config()
|
||||
.size({ (int)width, (int)height })
|
||||
.size({ (int)rsx::apply_resolution_scale((u16)width, true), (int)rsx::apply_resolution_scale((u16)height, true) })
|
||||
.type(format.type)
|
||||
.format(format.format)
|
||||
.internal_format(format.internal_format)
|
||||
@ -247,7 +260,7 @@ struct gl_render_target_traits
|
||||
return false;
|
||||
|
||||
auto internal_fmt = rsx::internals::sized_internal_format(format);
|
||||
return rtt->get_compatible_internal_format() == internal_fmt && rtt->width() == width && rtt->height() == height;
|
||||
return rtt->get_compatible_internal_format() == internal_fmt && rtt->matches_dimensions((u16)width, (u16)height);
|
||||
}
|
||||
|
||||
static
|
||||
@ -257,7 +270,7 @@ struct gl_render_target_traits
|
||||
return false;
|
||||
|
||||
// TODO: check format
|
||||
return rtt->width() == width && rtt->height() == height;
|
||||
return rtt->matches_dimensions((u16)width, (u16)height);
|
||||
}
|
||||
|
||||
// Note : pbo breaks fbo here so use classic texture copy
|
||||
|
@ -230,7 +230,7 @@ struct RSXFragmentProgram
|
||||
bool front_color_specular_output : 1;
|
||||
u32 texture_dimensions;
|
||||
|
||||
float texture_pitch_scale[16];
|
||||
std::array<float, 2> texture_scale[16];
|
||||
u8 textures_alpha_kill[16];
|
||||
u8 textures_zfunc[16];
|
||||
|
||||
|
@ -8,11 +8,13 @@
|
||||
|
||||
#include "Common/BufferUtils.h"
|
||||
#include "rsx_methods.h"
|
||||
#include "rsx_utils.h"
|
||||
|
||||
#include "Utilities/GSL.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
|
||||
#include <thread>
|
||||
#include <fenv.h>
|
||||
|
||||
class GSRender;
|
||||
|
||||
@ -391,6 +393,9 @@ namespace rsx
|
||||
// Raise priority above other threads
|
||||
thread_ctrl::set_native_priority(1);
|
||||
|
||||
// Round to nearest to deal with forward/reverse scaling
|
||||
fesetround(FE_TONEAREST);
|
||||
|
||||
// Deferred calls are used to batch draws together
|
||||
u32 deferred_primitive_type = 0;
|
||||
u32 deferred_call_size = 0;
|
||||
@ -790,24 +795,33 @@ namespace rsx
|
||||
void thread::fill_fragment_state_buffer(void *buffer, const RSXFragmentProgram &fragment_program)
|
||||
{
|
||||
const u32 is_alpha_tested = rsx::method_registers.alpha_test_enabled();
|
||||
const float alpha_ref = rsx::method_registers.alpha_ref() / 255.f;
|
||||
const f32 alpha_ref = rsx::method_registers.alpha_ref() / 255.f;
|
||||
const f32 fog0 = rsx::method_registers.fog_params_0();
|
||||
const f32 fog1 = rsx::method_registers.fog_params_1();
|
||||
const u32 alpha_func = static_cast<u32>(rsx::method_registers.alpha_func());
|
||||
const u32 fog_mode = static_cast<u32>(rsx::method_registers.fog_equation());
|
||||
const u32 window_origin = static_cast<u32>(rsx::method_registers.shader_window_origin());
|
||||
|
||||
// Generate wpos coeffecients
|
||||
// wpos equation is now as follows:
|
||||
// wpos.y = (frag_coord / resolution_scale) * ((window_origin!=top)?-1.: 1.) + ((window_origin!=top)? window_height : 0)
|
||||
// wpos.x = (frag_coord / resolution_scale)
|
||||
// wpos.zw = frag_coord.zw
|
||||
|
||||
const auto window_origin = rsx::method_registers.shader_window_origin();
|
||||
const u32 window_height = rsx::method_registers.shader_window_height();
|
||||
const float one = 1.f;
|
||||
const f32 resolution_scale = rsx::get_resolution_scale();
|
||||
const f32 wpos_scale = (window_origin == rsx::window_origin::top) ? (1.f / resolution_scale) : (-1.f / resolution_scale);
|
||||
const f32 wpos_bias = (window_origin == rsx::window_origin::top) ? 0.f : window_height;
|
||||
|
||||
u32 *dst = static_cast<u32*>(buffer);
|
||||
|
||||
stream_vector(dst, (u32&)fog0, (u32&)fog1, is_alpha_tested, (u32&)alpha_ref);
|
||||
stream_vector(dst + 4, alpha_func, fog_mode, window_origin, window_height);
|
||||
stream_vector(dst + 4, alpha_func, fog_mode, (u32&)wpos_scale, (u32&)wpos_bias);
|
||||
|
||||
size_t offset = 8;
|
||||
for (int index = 0; index < 16; ++index)
|
||||
{
|
||||
stream_vector(&dst[offset], (u32&)fragment_program.texture_pitch_scale[index], (u32&)one, 0U, 0U);
|
||||
stream_vector(&dst[offset], (u32&)fragment_program.texture_scale[index][0], (u32&)fragment_program.texture_scale[index][1], 0U, 0U);
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
@ -1305,10 +1319,13 @@ namespace rsx
|
||||
result.shadow_textures = 0;
|
||||
|
||||
std::array<texture_dimension_extended, 16> texture_dimensions;
|
||||
const auto resolution_scale = rsx::get_resolution_scale();
|
||||
|
||||
for (u32 i = 0; i < rsx::limits::fragment_textures_count; ++i)
|
||||
{
|
||||
auto &tex = rsx::method_registers.fragment_textures[i];
|
||||
result.texture_pitch_scale[i] = 1.f;
|
||||
result.texture_scale[i][0] = 1.f;
|
||||
result.texture_scale[i][1] = 1.f;
|
||||
result.textures_alpha_kill[i] = 0;
|
||||
result.textures_zfunc[i] = 0;
|
||||
|
||||
@ -1345,14 +1362,23 @@ namespace rsx
|
||||
if (surface_exists && surface_pitch)
|
||||
{
|
||||
if (raw_format & CELL_GCM_TEXTURE_UN)
|
||||
result.texture_pitch_scale[i] = (float)surface_pitch / tex.pitch();
|
||||
{
|
||||
result.texture_scale[i][0] = (resolution_scale * (float)surface_pitch) / tex.pitch();
|
||||
result.texture_scale[i][1] = resolution_scale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::tie(surface_exists, surface_pitch) = get_surface_info(texaddr, tex, true);
|
||||
if (surface_exists)
|
||||
{
|
||||
u32 format = raw_format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||
if (raw_format & CELL_GCM_TEXTURE_UN)
|
||||
{
|
||||
result.texture_scale[i][0] = (resolution_scale * (float)surface_pitch) / tex.pitch();
|
||||
result.texture_scale[i][1] = resolution_scale;
|
||||
}
|
||||
|
||||
const u32 format = raw_format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||
switch (format)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||
|
@ -166,8 +166,8 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
||||
OS << " float alpha_ref;\n";
|
||||
OS << " uint alpha_func;\n";
|
||||
OS << " uint fog_mode;\n";
|
||||
OS << " uint window_origin;\n";
|
||||
OS << " uint window_height;\n";
|
||||
OS << " float wpos_scale;\n";
|
||||
OS << " float wpos_bias;\n";
|
||||
OS << " vec4 texture_parameters[16];\n";
|
||||
OS << "};\n";
|
||||
|
||||
@ -253,8 +253,7 @@ void VKFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
|
||||
}
|
||||
|
||||
OS << " vec4 ssa = gl_FrontFacing ? vec4(1.) : vec4(-1.);\n";
|
||||
OS << " vec4 wpos = gl_FragCoord;\n";
|
||||
OS << " if (window_origin != 0) wpos.y = window_height - wpos.y;\n";
|
||||
OS << " vec4 wpos = get_wpos();\n";
|
||||
|
||||
bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output);
|
||||
|
||||
|
@ -1266,17 +1266,19 @@ void VKGSRender::end()
|
||||
|
||||
void VKGSRender::set_viewport()
|
||||
{
|
||||
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();
|
||||
const auto clip_width = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_width(), true);
|
||||
const auto clip_height = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_height(), true);
|
||||
u16 scissor_x = rsx::apply_resolution_scale(rsx::method_registers.scissor_origin_x(), false);
|
||||
u16 scissor_w = rsx::apply_resolution_scale(rsx::method_registers.scissor_width(), true);
|
||||
u16 scissor_y = rsx::apply_resolution_scale(rsx::method_registers.scissor_origin_y(), false);
|
||||
u16 scissor_h = rsx::apply_resolution_scale(rsx::method_registers.scissor_height(), true);
|
||||
|
||||
//NOTE: The scale_offset matrix already has viewport matrix factored in
|
||||
VkViewport viewport = {};
|
||||
viewport.x = 0;
|
||||
viewport.y = 0;
|
||||
viewport.width = rsx::method_registers.surface_clip_width();
|
||||
viewport.height = rsx::method_registers.surface_clip_height();
|
||||
viewport.width = clip_width;
|
||||
viewport.height = clip_height;
|
||||
viewport.minDepth = 0.f;
|
||||
viewport.maxDepth = 1.f;
|
||||
|
||||
@ -1341,13 +1343,14 @@ void VKGSRender::clear_surface(u32 mask)
|
||||
std::vector<VkClearAttachment> clear_descriptors;
|
||||
VkClearValue depth_stencil_clear_values, color_clear_values;
|
||||
|
||||
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();
|
||||
const auto scale = rsx::get_resolution_scale();
|
||||
u16 scissor_x = rsx::apply_resolution_scale(rsx::method_registers.scissor_origin_x(), false);
|
||||
u16 scissor_w = rsx::apply_resolution_scale(rsx::method_registers.scissor_width(), true);
|
||||
u16 scissor_y = rsx::apply_resolution_scale(rsx::method_registers.scissor_origin_y(), false);
|
||||
u16 scissor_h = rsx::apply_resolution_scale(rsx::method_registers.scissor_height(), true);
|
||||
|
||||
const u32 fb_width = m_draw_fbo->width();
|
||||
const u32 fb_height = m_draw_fbo->height();
|
||||
const u16 fb_width = m_draw_fbo->width();
|
||||
const u16 fb_height = m_draw_fbo->height();
|
||||
|
||||
//clip region
|
||||
std::tie(scissor_x, scissor_y, scissor_w, scissor_h) = rsx::clip_region<u16>(fb_width, fb_height, scissor_x, scissor_y, scissor_w, scissor_h, true);
|
||||
@ -2086,14 +2089,14 @@ void VKGSRender::prepare_rtts()
|
||||
const u32 surface_pitchs[] = { rsx::method_registers.surface_a_pitch(), rsx::method_registers.surface_b_pitch(),
|
||||
rsx::method_registers.surface_c_pitch(), rsx::method_registers.surface_d_pitch() };
|
||||
|
||||
const auto fbo_width = rsx::apply_resolution_scale(clip_width, true);
|
||||
const auto fbo_height = rsx::apply_resolution_scale(clip_height, true);
|
||||
|
||||
if (m_draw_fbo)
|
||||
{
|
||||
const u32 fb_width = m_draw_fbo->width();
|
||||
const u32 fb_height = m_draw_fbo->height();
|
||||
|
||||
bool really_changed = false;
|
||||
|
||||
if (fb_width == clip_width && fb_height == clip_height)
|
||||
if (m_draw_fbo->width() == fbo_width && m_draw_fbo->height() == clip_height)
|
||||
{
|
||||
for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i)
|
||||
{
|
||||
@ -2215,7 +2218,7 @@ void VKGSRender::prepare_rtts()
|
||||
|
||||
for (auto &fbo : m_framebuffers_to_clean)
|
||||
{
|
||||
if (fbo->matches(bound_images, clip_width, clip_height))
|
||||
if (fbo->matches(bound_images, fbo_width, fbo_height))
|
||||
{
|
||||
m_draw_fbo.swap(fbo);
|
||||
m_draw_fbo->reset_refs();
|
||||
@ -2263,7 +2266,7 @@ void VKGSRender::prepare_rtts()
|
||||
if (m_draw_fbo)
|
||||
m_framebuffers_to_clean.push_back(std::move(m_draw_fbo));
|
||||
|
||||
m_draw_fbo.reset(new vk::framebuffer_holder(*m_device, current_render_pass, clip_width, clip_height, std::move(fbo_images)));
|
||||
m_draw_fbo.reset(new vk::framebuffer_holder(*m_device, current_render_pass, fbo_width, fbo_height, std::move(fbo_images)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "../Common/surface_store.h"
|
||||
#include "../Common/TextureUtils.h"
|
||||
#include "VKFormats.h"
|
||||
#include "../rsx_utils.h"
|
||||
|
||||
struct ref_counted
|
||||
{
|
||||
@ -59,12 +60,12 @@ namespace vk
|
||||
|
||||
u16 get_surface_width() const override
|
||||
{
|
||||
return width();
|
||||
return rsx::apply_inverse_resolution_scale(width(), true);
|
||||
}
|
||||
|
||||
u16 get_surface_height() const override
|
||||
{
|
||||
return height();
|
||||
return rsx::apply_inverse_resolution_scale(height(), true);
|
||||
}
|
||||
|
||||
u16 get_rsx_pitch() const override
|
||||
@ -76,6 +77,12 @@ namespace vk
|
||||
{
|
||||
return native_pitch;
|
||||
}
|
||||
|
||||
bool matches_dimensions(u16 _width, u16 _height) const
|
||||
{
|
||||
//Use foward scaling to account for rounding and clamping errors
|
||||
return (rsx::apply_resolution_scale(_width, true) == width()) && (rsx::apply_resolution_scale(_height, true) == height());
|
||||
}
|
||||
};
|
||||
|
||||
struct framebuffer_holder: public vk::framebuffer, public ref_counted
|
||||
@ -114,7 +121,7 @@ namespace rsx
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
VK_IMAGE_TYPE_2D,
|
||||
requested_format,
|
||||
static_cast<uint32_t>(width), static_cast<uint32_t>(height), 1, 1, 1,
|
||||
static_cast<uint32_t>(rsx::apply_resolution_scale((u16)width, true)), static_cast<uint32_t>(rsx::apply_resolution_scale((u16)height, true)), 1, 1, 1,
|
||||
VK_SAMPLE_COUNT_1_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
@ -158,12 +165,14 @@ namespace rsx
|
||||
if (requested_format != VK_FORMAT_D16_UNORM)
|
||||
range.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
const auto scale = rsx::get_resolution_scale();
|
||||
|
||||
std::unique_ptr<vk::render_target> ds;
|
||||
ds.reset(new vk::render_target(device, mem_mapping.device_local,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
VK_IMAGE_TYPE_2D,
|
||||
requested_format,
|
||||
static_cast<uint32_t>(width), static_cast<uint32_t>(height), 1, 1, 1,
|
||||
static_cast<uint32_t>(rsx::apply_resolution_scale((u16)width, true)), static_cast<uint32_t>(rsx::apply_resolution_scale((u16)height, true)), 1, 1, 1,
|
||||
VK_SAMPLE_COUNT_1_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
@ -202,8 +211,8 @@ namespace rsx
|
||||
{
|
||||
info->rsx_pitch = surface->rsx_pitch;
|
||||
info->native_pitch = surface->native_pitch;
|
||||
info->surface_width = surface->info.extent.width;
|
||||
info->surface_height = surface->info.extent.height;
|
||||
info->surface_width = surface->get_surface_width();
|
||||
info->surface_height = surface->get_surface_height();
|
||||
info->bpp = static_cast<u8>(info->native_pitch / info->surface_width);
|
||||
}
|
||||
|
||||
@ -260,8 +269,7 @@ namespace rsx
|
||||
VkFormat fmt = vk::get_compatible_surface_format(format).first;
|
||||
|
||||
if (rtt->info.format == fmt &&
|
||||
rtt->info.extent.width == width &&
|
||||
rtt->info.extent.height == height)
|
||||
rtt->matches_dimensions((u16)width, (u16)height))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -272,8 +280,7 @@ namespace rsx
|
||||
if (check_refs && ds->deref_count == 0) //Surface may still have read refs from data 'copy'
|
||||
return false;
|
||||
|
||||
if (ds->info.extent.width == width &&
|
||||
ds->info.extent.height == height)
|
||||
if (ds->matches_dimensions((u16)width, (u16)height))
|
||||
{
|
||||
//Check format
|
||||
switch (ds->info.format)
|
||||
|
@ -207,4 +207,30 @@ namespace rsx
|
||||
|
||||
return std::make_tuple(x, y, width, height);
|
||||
}
|
||||
|
||||
static inline f32 get_resolution_scale()
|
||||
{
|
||||
return g_cfg.video.strict_rendering_mode? 1.f : ((f32)g_cfg.video.resolution_scale_percent / 100.f);
|
||||
}
|
||||
|
||||
static inline int get_resolution_scale_percent()
|
||||
{
|
||||
return g_cfg.video.strict_rendering_mode ? 100 : g_cfg.video.resolution_scale_percent;
|
||||
}
|
||||
|
||||
static inline const u16 apply_resolution_scale(u16 value, bool clamp)
|
||||
{
|
||||
if (clamp)
|
||||
return (u16)std::max((get_resolution_scale_percent() * value) / 100, 1);
|
||||
else
|
||||
return (get_resolution_scale_percent() * value) / 100;
|
||||
}
|
||||
|
||||
static inline const u16 apply_inverse_resolution_scale(u16 value, bool clamp)
|
||||
{
|
||||
if (clamp)
|
||||
return (u16)std::max((value * 100) / get_resolution_scale_percent(), 1);
|
||||
else
|
||||
return (value * 100) / get_resolution_scale_percent();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user