Skip to content

Commit

Permalink
Merge branch 'Vita3K:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
backgamon authored Feb 11, 2024
2 parents 0d2d51e + aa2c1cb commit da11765
Show file tree
Hide file tree
Showing 17 changed files with 100 additions and 86 deletions.
2 changes: 1 addition & 1 deletion vita3k/config/include/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ enum PerfomanceOverleyPosition {
code(std::string, "backend-renderer", "OpenGL", backend_renderer) \
code(int, "gpu-idx", 0, gpu_idx) \
code(bool, "high-accuracy", true, high_accuracy) \
code(int, "resolution-multiplier", 1, resolution_multiplier) \
code(float, "resolution-multiplier", 1.0f, resolution_multiplier) \
code(bool, "disable-surface-sync", true, disable_surface_sync) \
code(std::string, "screen-filter", "Bilinear", screen_filter) \
code(bool, "v-sync", true, v_sync) \
Expand Down
2 changes: 1 addition & 1 deletion vita3k/config/include/config/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ struct Config : YamlLoader {
bool ngs_enable = true;
bool pstv_mode = false;
bool high_accuracy = false;
int resolution_multiplier = 1;
float resolution_multiplier = 1.0f;
bool disable_surface_sync = false;
std::string screen_filter = "Bilinear";
bool v_sync = true;
Expand Down
36 changes: 22 additions & 14 deletions vita3k/gui/src/settings_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ static bool get_custom_config(GuiState &gui, EmuEnvState &emuenv, const std::str
if (!config_child.child("gpu").empty()) {
const auto gpu_child = config_child.child("gpu");
config.high_accuracy = gpu_child.attribute("high-accuracy").as_bool();
config.resolution_multiplier = gpu_child.attribute("resolution-multiplier").as_int();
config.resolution_multiplier = gpu_child.attribute("resolution-multiplier").as_float();
config.disable_surface_sync = gpu_child.attribute("disable-surface-sync").as_bool();
config.screen_filter = gpu_child.attribute("screen-filter").as_string();
config.v_sync = gpu_child.attribute("v-sync").as_bool();
Expand Down Expand Up @@ -629,7 +629,13 @@ void draw_settings_dialog(GuiState &gui, EmuEnvState &emuenv) {
ImGui::SetTooltip("%s", lang.gpu["v_sync_description"].c_str());
ImGui::SameLine();
}
if (!is_vulkan || emuenv.renderer->features.support_memory_mapping) {

const bool has_integer_multiplier = static_cast<int>(config.resolution_multiplier * 4.0f) % 4 == 0;
// OpenGL does not support surface sync with a non-integer resolution multiplier
if (!is_vulkan && has_integer_multiplier)
config.disable_surface_sync = true;

if ((!is_vulkan && has_integer_multiplier) || emuenv.renderer->features.support_memory_mapping) {
// surface sync is supported on vulkan only when memory mapping is enabled
ImGui::Checkbox(lang.gpu["disable_surface_sync"].c_str(), &config.disable_surface_sync);
if (ImGui::IsItemHovered())
Expand Down Expand Up @@ -679,38 +685,40 @@ void draw_settings_dialog(GuiState &gui, EmuEnvState &emuenv) {
ImGui::TextColored(GUI_COLOR_TEXT_TITLE, "%s", lang.gpu["internal_resolution_upscaling"].c_str());
ImGui::Spacing();
ImGui::PushID("Res scal");
if (config.resolution_multiplier == 1)
if (config.resolution_multiplier == 0.5f)
ImGui::BeginDisabled();
if (ImGui::Button("<", ImVec2(20.f * SCALE.x, 0)))
--config.resolution_multiplier;
if (config.resolution_multiplier == 1)
config.resolution_multiplier -= 0.25f;
if (config.resolution_multiplier == 0.5f)
ImGui::EndDisabled();
ImGui::SameLine(0, 5.f * SCALE.x);
ImGui::PushItemWidth(-100.f * SCALE.x);
if (ImGui::SliderInt("##res_scal", &config.resolution_multiplier, 1, 8, fmt::format("{}x", config.resolution_multiplier).c_str(), ImGuiSliderFlags_None)) {
if (config.resolution_multiplier > 1 && !is_vulkan)
int slider_position = static_cast<int>(config.resolution_multiplier * 4);
if (ImGui::SliderInt("##res_scal", &slider_position, 2, 32, fmt::format("{}x", config.resolution_multiplier).c_str(), ImGuiSliderFlags_None)) {
config.resolution_multiplier = static_cast<float>(slider_position) / 4.0f;
if (config.resolution_multiplier != 1.0f && !is_vulkan)
config.disable_surface_sync = true;
}
ImGui::PopItemWidth();
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", lang.gpu["internal_resolution_upscaling_description"].c_str());
ImGui::SameLine(0, 5 * SCALE.x);
if (config.resolution_multiplier == 8)
if (config.resolution_multiplier == 8.0f)
ImGui::BeginDisabled();
if (ImGui::Button(">", ImVec2(20.f * SCALE.x, 0)))
++config.resolution_multiplier;
if (config.resolution_multiplier == 8)
config.resolution_multiplier += 0.25f;
if (config.resolution_multiplier == 8.0f)
ImGui::EndDisabled();
ImGui::SameLine();
if ((config.resolution_multiplier == 1) && !config.disable_surface_sync)
if ((config.resolution_multiplier == 1.0f) && !config.disable_surface_sync)
ImGui::BeginDisabled();
if (ImGui::Button(lang.gpu["reset"].c_str(), ImVec2(60.f * SCALE.x, 0)))
config.resolution_multiplier = 1;
config.resolution_multiplier = 1.0f;

if ((config.resolution_multiplier == 1) && !config.disable_surface_sync)
if ((config.resolution_multiplier == 1.0f) && !config.disable_surface_sync)
ImGui::EndDisabled();
ImGui::Spacing();
const auto res_scal = fmt::format("{}x{}", 960 * config.resolution_multiplier, 544 * config.resolution_multiplier);
const auto res_scal = fmt::format("{}x{}", static_cast<int>(960 * config.resolution_multiplier), static_cast<int>(544 * config.resolution_multiplier));
ImGui::SetCursorPosX((ImGui::GetWindowWidth() / 2.f) - (ImGui::CalcTextSize(res_scal.c_str()).x / 2.f) - (35.f * SCALE.x));
ImGui::Text("%s", res_scal.c_str());
ImGui::PopID();
Expand Down
4 changes: 2 additions & 2 deletions vita3k/renderer/include/renderer/gl/surface_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ class GLSurfaceCache {
target = new_target;
}

GLuint sourcing_color_surface_for_presentation(Ptr<const void> address, uint32_t width, uint32_t height, const std::uint32_t pitch, float *uvs, const int res_multiplier, SceFVector2 &texture_size);
std::vector<uint32_t> dump_frame(Ptr<const void> address, uint32_t width, uint32_t height, uint32_t pitch, int res_multiplier, bool support_get_texture_sub_image);
GLuint sourcing_color_surface_for_presentation(Ptr<const void> address, uint32_t width, uint32_t height, const std::uint32_t pitch, float *uvs, const float res_multiplier, SceFVector2 &texture_size);
std::vector<uint32_t> dump_frame(Ptr<const void> address, uint32_t width, uint32_t height, uint32_t pitch, float res_multiplier, bool support_get_texture_sub_image);
};
} // namespace gl
} // namespace renderer
2 changes: 1 addition & 1 deletion vita3k/renderer/include/renderer/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct State {

Backend current_backend;
FeatureState features;
int res_multiplier;
float res_multiplier;
bool disable_surface_sync;
bool stretch_the_display_area;

Expand Down
4 changes: 2 additions & 2 deletions vita3k/renderer/src/creation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ COMMAND(handle_create_render_target) {
uint16_t nb_macroblocks_y = (params->flags >> 12) & 0b111;

// the width and height should be multiple of 128
(*render_target)->macroblock_width = (params->width / nb_macroblocks_x) * renderer.res_multiplier;
(*render_target)->macroblock_height = (params->height / nb_macroblocks_y) * renderer.res_multiplier;
(*render_target)->macroblock_width = static_cast<uint16_t>((params->width / nb_macroblocks_x) * renderer.res_multiplier);
(*render_target)->macroblock_height = static_cast<uint16_t>((params->height / nb_macroblocks_y) * renderer.res_multiplier);
}

complete_command(renderer, helper, result);
Expand Down
2 changes: 1 addition & 1 deletion vita3k/renderer/src/gl/draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ void draw(GLState &renderer, GLContext &context, const FeatureState &features, S
}
frag_ublock.writing_mask = context.record.writing_mask;
frag_ublock.use_raw_image = static_cast<float>(use_raw_image);
frag_ublock.res_multiplier = static_cast<float>(renderer.res_multiplier);
frag_ublock.res_multiplier = renderer.res_multiplier;
const bool has_msaa = context.render_target->multisample_mode;
const bool has_downscale = context.record.color_surface.downscale;
if (has_msaa && !has_downscale)
Expand Down
23 changes: 12 additions & 11 deletions vita3k/renderer/src/gl/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,8 @@ bool create(GLState &state, std::unique_ptr<RenderTarget> &rt, const SceGxmRende
return false;
}

render_target->width = params.width * state.res_multiplier;
render_target->height = params.height * state.res_multiplier;
render_target->width = static_cast<uint16_t>(params.width * state.res_multiplier);
render_target->height = static_cast<uint16_t>(params.height * state.res_multiplier);

render_target->attachments.init(reinterpret_cast<renderer::Generator *>(glGenTextures), reinterpret_cast<renderer::Deleter *>(glDeleteTextures));

Expand All @@ -317,7 +317,7 @@ bool create(GLState &state, std::unique_ptr<RenderTarget> &rt, const SceGxmRende
glBindTexture(GL_TEXTURE_2D, render_target->masktexture[0]);
// we need to make the masktexture format immutable, otherwise image load operations
// won't work on mesa drivers
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, params.width * state.res_multiplier, params.height * state.res_multiplier);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, render_target->width, render_target->height);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindFramebuffer(GL_FRAMEBUFFER, render_target->maskbuffer[0]);
Expand Down Expand Up @@ -443,7 +443,7 @@ static std::map<SceGxmColorFormat, std::pair<GLenum, GLenum>> GXM_COLOR_FORMAT_T

static bool format_need_temp_storage(const GLState &state, SceGxmColorSurface &surface, std::vector<std::uint8_t> &storage, const std::uint32_t width, const std::uint32_t height) {
size_t needed_pixels;
if (state.res_multiplier == 1) {
if (state.res_multiplier == 1.0f) {
needed_pixels = surface.strideInPixels * height;
} else {
// width and height is already upscaled
Expand All @@ -455,7 +455,7 @@ static bool format_need_temp_storage(const GLState &state, SceGxmColorSurface &s
return true;
}

if (state.res_multiplier > 1) {
if (state.res_multiplier > 1.0f) {
storage.resize(needed_pixels * gxm::bits_per_pixel(gxm::get_base_format(surface.colorFormat)) >> 3);
return true;
}
Expand All @@ -471,7 +471,7 @@ static void post_process_pixels_data(GLState &renderer, std::uint32_t *pixels, s
const bool is_U8U8U8_RGBA = surface.colorFormat == SCE_GXM_COLOR_FORMAT_U8U8U8U8_RGBA;
const bool is_SE5M9M9M9 = (surface.colorFormat == SCE_GXM_COLOR_FORMAT_SE5M9M9M9_RGB) || (surface.colorFormat == SCE_GXM_COLOR_FORMAT_SE5M9M9M9_BGR);

const int multiplier = renderer.res_multiplier;
const int multiplier = static_cast<int>(renderer.res_multiplier);
if (multiplier > 1 || is_U8U8U8_RGBA || is_SE5M9M9M9) {
// TODO: do this on the GPU instead (using texture blitting?)
const int bytes_per_output_pixel = (gxm::bits_per_pixel(gxm::get_base_format(surface.colorFormat)) + 7) >> 3;
Expand Down Expand Up @@ -608,11 +608,12 @@ void get_surface_data(GLState &renderer, GLContext &context, uint32_t *pixels, S
uint32_t width = surface.width;
uint32_t height = surface.height;

if (renderer.res_multiplier == 1) {
const int res_multiplier = static_cast<int>(renderer.res_multiplier);
if (res_multiplier == 1) {
glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(surface.strideInPixels));
} else {
width *= renderer.res_multiplier;
height *= renderer.res_multiplier;
width *= res_multiplier;
height *= res_multiplier;
glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(width));
}

Expand Down Expand Up @@ -723,8 +724,8 @@ std::vector<uint32_t> GLState::dump_frame(DisplayState &display, uint32_t &width
frame = display.next_rendered_frame;
}

width = frame.image_size.x * res_multiplier;
height = frame.image_size.y * res_multiplier;
width = static_cast<uint32_t>(frame.image_size.x * res_multiplier);
height = static_cast<uint32_t>(frame.image_size.y * res_multiplier);
return surface_cache.dump_frame(frame.base, width, height, frame.pitch, res_multiplier, features.support_get_texture_sub_image);
}

Expand Down
33 changes: 16 additions & 17 deletions vita3k/renderer/src/gl/surface_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ GLuint GLSurfaceCache::retrieve_color_surface_texture_handle(const State &state,
const uint32_t original_width = width;
const uint32_t original_height = height;

width *= state.res_multiplier;
height *= state.res_multiplier;
width = static_cast<uint16_t>(width * state.res_multiplier);
height = static_cast<uint16_t>(height * state.res_multiplier);

// Of course, this works under the assumption that range must be unique :D
auto ite = color_surface_textures.lower_bound(key);
Expand Down Expand Up @@ -271,8 +271,8 @@ GLuint GLSurfaceCache::retrieve_color_surface_texture_handle(const State &state,

if (castable) {
const std::size_t data_delta = address.address() - ite->first;
std::size_t start_sourced_line = (data_delta / bytes_per_stride) * state.res_multiplier;
std::size_t start_x = (data_delta % bytes_per_stride) / color::bytes_per_pixel(base_format) * state.res_multiplier;
std::size_t start_sourced_line = static_cast<size_t>((data_delta / bytes_per_stride) * state.res_multiplier);
std::size_t start_x = static_cast<size_t>((data_delta % bytes_per_stride) / color::bytes_per_pixel(base_format) * state.res_multiplier);

if (static_cast<std::uint16_t>(start_sourced_line + height) > info.height) {
LOG_ERROR("Trying to present non-existen segment in cached color surface!");
Expand Down Expand Up @@ -521,16 +521,15 @@ GLuint GLSurfaceCache::retrieve_depth_stencil_texture_handle(const State &state,
return 0;
}

force_width *= state.res_multiplier;
force_height *= state.res_multiplier;

if (force_width < 0) {
if (force_width > 0)
force_width = static_cast<int32_t>(force_width * state.res_multiplier);
else
force_width = target->width;
}

if (force_height < 0) {
if (force_height > 0)
force_height = static_cast<int32_t>(force_height * state.res_multiplier);
else
force_height = target->height;
}

const bool is_stencil_only = surface.depth_data.address() == 0;
std::size_t found_index = static_cast<std::size_t>(-1);
Expand Down Expand Up @@ -713,14 +712,14 @@ GLuint GLSurfaceCache::retrieve_framebuffer_handle(const State &state, const Mem
return fb[0];
}

GLuint GLSurfaceCache::sourcing_color_surface_for_presentation(Ptr<const void> address, uint32_t width, uint32_t height, const std::uint32_t pitch, float *uvs, const int res_multiplier, SceFVector2 &texture_size) {
GLuint GLSurfaceCache::sourcing_color_surface_for_presentation(Ptr<const void> address, uint32_t width, uint32_t height, const std::uint32_t pitch, float *uvs, const float res_multiplier, SceFVector2 &texture_size) {
auto ite = color_surface_textures.lower_bound(address.address());
if (ite == color_surface_textures.end()) {
return 0;
}

width *= res_multiplier;
height *= res_multiplier;
width = static_cast<uint32_t>(width * res_multiplier);
height = static_cast<uint32_t>(height * res_multiplier);

const GLColorSurfaceCacheInfo &info = *ite->second;

Expand All @@ -729,7 +728,7 @@ GLuint GLSurfaceCache::sourcing_color_surface_for_presentation(Ptr<const void> a
const std::size_t data_delta = address.address() - ite->first;
std::uint32_t limited_height = height;
if ((data_delta % (pitch * 4)) == 0) {
std::uint32_t start_sourced_line = (data_delta / (pitch * 4)) * res_multiplier;
std::uint32_t start_sourced_line = static_cast<uint32_t>((data_delta / (pitch * 4)) * res_multiplier);
if ((start_sourced_line + height) > info.height) {
// Sometimes the surface is just missing a little bit of lines
if (start_sourced_line < info.height) {
Expand Down Expand Up @@ -758,7 +757,7 @@ GLuint GLSurfaceCache::sourcing_color_surface_for_presentation(Ptr<const void> a
return 0;
}

std::vector<uint32_t> GLSurfaceCache::dump_frame(Ptr<const void> address, uint32_t width, uint32_t height, uint32_t pitch, int res_multiplier, bool support_get_texture_sub_image) {
std::vector<uint32_t> GLSurfaceCache::dump_frame(Ptr<const void> address, uint32_t width, uint32_t height, uint32_t pitch, float res_multiplier, bool support_get_texture_sub_image) {
auto ite = color_surface_textures.lower_bound(address.address());
if (ite == color_surface_textures.end() || ite->second->pixel_stride != pitch) {
return {};
Expand All @@ -771,7 +770,7 @@ std::vector<uint32_t> GLSurfaceCache::dump_frame(Ptr<const void> address, uint32
if (info.pixel_stride != pitch || data_delta % pitch_byte != 0)
return {};

const uint32_t line_delta = (data_delta / pitch_byte) * res_multiplier;
const uint32_t line_delta = static_cast<uint32_t>((data_delta / pitch_byte) * res_multiplier);
if (line_delta >= info.height)
return {};

Expand Down
6 changes: 4 additions & 2 deletions vita3k/renderer/src/gl/sync_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ void sync_viewport_flat(const GLState &state, GLContext &context) {
const GLsizei display_w = context.record.color_surface.width;
const GLsizei display_h = context.record.color_surface.height;

glViewport(0, (context.current_framebuffer_height - display_h) * state.res_multiplier, display_w * state.res_multiplier, display_h * state.res_multiplier);
glViewport(0, static_cast<GLint>((context.current_framebuffer_height - display_h) * state.res_multiplier),
static_cast<GLsizei>(display_w * state.res_multiplier), static_cast<GLsizei>(display_h * state.res_multiplier));
glDepthRange(0, 1);
}

Expand Down Expand Up @@ -161,7 +162,8 @@ void sync_clipping(const GLState &state, GLContext &context) {
break;
case SCE_GXM_REGION_CLIP_OUTSIDE:
glEnable(GL_SCISSOR_TEST);
glScissor(scissor_x * state.res_multiplier, scissor_y * state.res_multiplier, scissor_w * state.res_multiplier, scissor_h * state.res_multiplier);
glScissor(static_cast<GLint>(scissor_x * state.res_multiplier), static_cast<GLint>(scissor_y * state.res_multiplier),
static_cast<GLsizei>(scissor_w * state.res_multiplier), static_cast<GLsizei>(scissor_h * state.res_multiplier));
break;
case SCE_GXM_REGION_CLIP_INSIDE:
// TODO: Implement SCE_GXM_REGION_CLIP_INSIDE
Expand Down
4 changes: 4 additions & 0 deletions vita3k/renderer/src/scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ COMMAND(handle_sync_surface_data) {
}
}

// additional check to make sure we never try to perform surface sync on OpenGL with a non-integer resolution multiplier
if (renderer.current_backend == Backend::OpenGL && static_cast<int>(renderer.res_multiplier * 4.0f) % 4 != 0)
renderer.disable_surface_sync = true;

if (renderer.disable_surface_sync || renderer.current_backend == Backend::Vulkan) {
if (helper.cmd->status) {
complete_command(renderer, helper, 0);
Expand Down
2 changes: 1 addition & 1 deletion vita3k/renderer/src/texture/replacement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ void TextureCache::export_texture_impl(SceGxmTextureBaseFormat base_format, uint
}
} else {
// alpha is already linear
for (uint32_t i = 0; i < nb_pixels * 4; i++) {
for (uint32_t i = 0; i < nb_pixels; i++) {
pixels[i * 4 + 0] = convert_to_linear(pixels[i * 4 + 0]);
pixels[i * 4 + 1] = convert_to_linear(pixels[i * 4 + 1]);
pixels[i * 4 + 2] = convert_to_linear(pixels[i * 4 + 2]);
Expand Down
Loading

0 comments on commit da11765

Please sign in to comment.