Prepare frontend for multiple graphics APIs (#6347)

* externals: Update dynarmic

* settings: Introduce GraphicsAPI enum

* For now it's OpenGL only but will be expanded upon later

* citra_qt: Introduce backend agnostic context management

* Mostly a direct port from yuzu

* core: Simplify context acquire

* settings: Add option to create debug contexts

* renderer_opengl: Abstract initialization to Driver

* This commit also updates glad and adds some useful extensions which we will use in part 2

* Rasterizer construction is moved to the specific renderer instead of RendererBase.
  Software rendering has been disable to achieve this but will be brought back in the next commit.

* video_core: Remove Init/Shutdown methods from renderer

* The constructor and destructor can do the same job

* In addition move opengl function loading to Qt since SDL already does this. Also remove ErrorVideoCore which is never reached

* citra_qt: Decouple software renderer from opengl part 1

* citra: Decouple software renderer from opengl part 2

* android: Decouple software renderer from opengl part 3

* swrasterizer: Decouple software renderer from opengl part 4

* This commit simply enforces the renderer naming conventions in the software renderer

* video_core: Move RendererBase to VideoCore

* video_core: De-globalize screenshot state

* video_core: Pass system to the renderers

* video_core: Commonize shader uniform data

* video_core: Abstract backend agnostic rasterizer operations

* bootmanager: Remove references to OpenGL for macOS

OpenGL macOS headers definitions clash heavily with each other

* citra_qt: Proper title for api settings

* video_core: Reduce boost usage

* bootmanager: Fix hide mouse option

Remove event handlers from RenderWidget for events that are
already handled by the parent GRenderWindow.
Also enable mouse tracking on the RenderWidget.

* android: Remove software from graphics api list

* code: Address review comments

* citra: Port per-game settings read

* Having to update the default value for all backends is a pain so lets centralize it

* android: Rename to OpenGLES

---------

Co-authored-by: MerryMage <MerryMage@users.noreply.github.com>
Co-authored-by: Vitor Kiguchi <vitor-kiguchi@hotmail.com>
This commit is contained in:
GPUCode 2023-03-27 14:29:17 +03:00 committed by GitHub
parent 9ef42040af
commit b5d6f645bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
99 changed files with 3165 additions and 4501 deletions

View file

@ -86,7 +86,7 @@ void UnitState::LoadInput(const ShaderRegs& config, const AttributeBuffer& input
}
}
static void CopyRegistersToOutput(const Common::Vec4<float24>* regs, u32 mask,
static void CopyRegistersToOutput(std::span<Common::Vec4<float24>, 16> regs, u32 mask,
AttributeBuffer& buffer) {
int output_i = 0;
for (int reg : Common::BitSet<u32>(mask)) {
@ -108,7 +108,7 @@ GSEmitter::~GSEmitter() {
delete handlers;
}
void GSEmitter::Emit(Common::Vec4<float24> (&output_regs)[16]) {
void GSEmitter::Emit(std::span<Common::Vec4<float24>, 16> output_regs) {
ASSERT(vertex_id < 3);
// TODO: This should be merged with UnitState::WriteOutput somehow
CopyRegistersToOutput(output_regs, output_mask, buffer[vertex_id]);

View file

@ -7,6 +7,7 @@
#include <array>
#include <cstddef>
#include <functional>
#include <span>
#include <type_traits>
#include <boost/serialization/access.hpp>
#include <boost/serialization/array.hpp>
@ -113,7 +114,7 @@ struct GSEmitter {
GSEmitter();
~GSEmitter();
void Emit(Common::Vec4<float24> (&output_regs)[16]);
void Emit(std::span<Common::Vec4<float24>, 16> output_regs);
private:
friend class boost::serialization::access;
@ -140,9 +141,9 @@ struct UnitState {
struct Registers {
// The registers are accessed by the shader JIT using SSE instructions, and are therefore
// required to be 16-byte aligned.
alignas(16) Common::Vec4<float24> input[16];
alignas(16) Common::Vec4<float24> temporary[16];
alignas(16) Common::Vec4<float24> output[16];
alignas(16) std::array<Common::Vec4<float24>, 16> input;
alignas(16) std::array<Common::Vec4<float24>, 16> temporary;
alignas(16) std::array<Common::Vec4<float24>, 16> output;
private:
friend class boost::serialization::access;

View file

@ -7,7 +7,6 @@
#include <cmath>
#include <numeric>
#include <boost/container/static_vector.hpp>
#include <boost/range/algorithm/fill.hpp>
#include <nihstro/shader_bytecode.h>
#include "common/assert.h"
#include "common/common_types.h"
@ -688,7 +687,7 @@ DebugData<true> InterpreterEngine::ProduceDebugInfo(const ShaderSetup& setup,
DebugData<true> debug_data;
// Setup input register table
boost::fill(state.registers.input, Common::Vec4<float24>::AssignToAll(float24::Zero()));
state.registers.input.fill(Common::Vec4<float24>::AssignToAll(float24::Zero()));
state.LoadInput(config, input);
RunInterpreter(setup, state, debug_data, setup.engine_data.entry_point);
return debug_data;

View file

@ -0,0 +1,78 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include "video_core/shader/shader.h"
#include "video_core/shader/shader_uniforms.h"
namespace Pica::Shader {
void PicaUniformsData::SetFromRegs(const Pica::ShaderRegs& regs,
const Pica::Shader::ShaderSetup& setup) {
std::transform(std::begin(setup.uniforms.b), std::end(setup.uniforms.b), std::begin(bools),
[](bool value) -> BoolAligned { return {value ? 1 : 0}; });
std::transform(std::begin(regs.int_uniforms), std::end(regs.int_uniforms), std::begin(i),
[](const auto& value) -> Common::Vec4u {
return {value.x.Value(), value.y.Value(), value.z.Value(), value.w.Value()};
});
std::transform(std::begin(setup.uniforms.f), std::end(setup.uniforms.f), std::begin(f),
[](const auto& value) -> Common::Vec4f {
return {value.x.ToFloat32(), value.y.ToFloat32(), value.z.ToFloat32(),
value.w.ToFloat32()};
});
}
constexpr std::string_view UniformBlockDefFormat = R"(
#define NUM_TEV_STAGES 6
#define NUM_LIGHTS 8
#define NUM_LIGHTING_SAMPLERS 24
struct LightSrc {{
vec3 specular_0;
vec3 specular_1;
vec3 diffuse;
vec3 ambient;
vec3 position;
vec3 spot_direction;
float dist_atten_bias;
float dist_atten_scale;
}};
layout ({}std140) uniform shader_data {{
int framebuffer_scale;
int alphatest_ref;
float depth_scale;
float depth_offset;
float shadow_bias_constant;
float shadow_bias_linear;
int scissor_x1;
int scissor_y1;
int scissor_x2;
int scissor_y2;
int fog_lut_offset;
int proctex_noise_lut_offset;
int proctex_color_map_offset;
int proctex_alpha_map_offset;
int proctex_lut_offset;
int proctex_diff_lut_offset;
float proctex_bias;
int shadow_texture_bias;
bool enable_clip1;
ivec4 lighting_lut_offset[NUM_LIGHTING_SAMPLERS / 4];
vec3 fog_color;
vec2 proctex_noise_f;
vec2 proctex_noise_a;
vec2 proctex_noise_p;
vec3 lighting_global_ambient;
LightSrc light_src[NUM_LIGHTS];
vec4 const_color[NUM_TEV_STAGES];
vec4 tev_combiner_buffer_color;
vec3 tex_lod_bias;
vec4 clip_coef;
}};
)";
std::string BuildShaderUniformDefinitions(const std::string& extra_layout_parameters) {
return fmt::format(UniformBlockDefFormat, extra_layout_parameters);
}
} // namespace Pica::Shader

View file

@ -0,0 +1,101 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "common/vector_math.h"
#include "video_core/regs_lighting.h"
namespace Pica {
struct ShaderRegs;
}
namespace Pica::Shader {
struct ShaderSetup;
enum class UniformBindings : u32 { Common, VS, GS };
struct LightSrc {
alignas(16) Common::Vec3f specular_0;
alignas(16) Common::Vec3f specular_1;
alignas(16) Common::Vec3f diffuse;
alignas(16) Common::Vec3f ambient;
alignas(16) Common::Vec3f position;
alignas(16) Common::Vec3f spot_direction; // negated
float dist_atten_bias;
float dist_atten_scale;
};
/**
* Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned
* NOTE: Always keep a vec4 at the end. The GL spec is not clear wether the alignment at
* the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.
* Not following that rule will cause problems on some AMD drivers.
*/
struct UniformData {
int framebuffer_scale;
int alphatest_ref;
float depth_scale;
float depth_offset;
float shadow_bias_constant;
float shadow_bias_linear;
int scissor_x1;
int scissor_y1;
int scissor_x2;
int scissor_y2;
int fog_lut_offset;
int proctex_noise_lut_offset;
int proctex_color_map_offset;
int proctex_alpha_map_offset;
int proctex_lut_offset;
int proctex_diff_lut_offset;
float proctex_bias;
int shadow_texture_bias;
alignas(4) bool enable_clip1;
alignas(16) Common::Vec4i lighting_lut_offset[LightingRegs::NumLightingSampler / 4];
alignas(16) Common::Vec3f fog_color;
alignas(8) Common::Vec2f proctex_noise_f;
alignas(8) Common::Vec2f proctex_noise_a;
alignas(8) Common::Vec2f proctex_noise_p;
alignas(16) Common::Vec3f lighting_global_ambient;
LightSrc light_src[8];
alignas(16) Common::Vec4f const_color[6]; // A vec4 color for each of the six tev stages
alignas(16) Common::Vec4f tev_combiner_buffer_color;
alignas(16) Common::Vec3f tex_lod_bias;
alignas(16) Common::Vec4f clip_coef;
};
static_assert(sizeof(UniformData) == 0x500,
"The size of the UniformData does not match the structure in the shader");
static_assert(sizeof(UniformData) < 16384,
"UniformData structure must be less than 16kb as per the OpenGL spec");
/**
* Uniform struct for the Uniform Buffer Object that contains PICA vertex/geometry shader uniforms.
* NOTE: the same rule from UniformData also applies here.
*/
struct PicaUniformsData {
void SetFromRegs(const ShaderRegs& regs, const ShaderSetup& setup);
struct BoolAligned {
alignas(16) int b;
};
std::array<BoolAligned, 16> bools;
alignas(16) std::array<Common::Vec4u, 4> i;
alignas(16) std::array<Common::Vec4f, 96> f;
};
struct VSUniformData {
PicaUniformsData uniforms;
};
static_assert(sizeof(VSUniformData) == 1856,
"The size of the VSUniformData does not match the structure in the shader");
static_assert(sizeof(VSUniformData) < 16384,
"VSUniformData structure must be less than 16kb as per the OpenGL spec");
std::string BuildShaderUniformDefinitions(const std::string& extra_layout_parameters = "");
} // namespace Pica::Shader