video_core: Move api agnostic uniform updates to RasterizerAccelerated

This commit is contained in:
GPUCode
2022-10-28 15:53:33 +03:00
parent 72f8d520c9
commit 8076d893db
6 changed files with 295 additions and 561 deletions

View File

@ -5,10 +5,25 @@
#include <limits> #include <limits>
#include "core/memory.h" #include "core/memory.h"
#include "video_core/rasterizer_accelerated.h" #include "video_core/rasterizer_accelerated.h"
#include "video_core/pica_state.h"
#include "video_core/video_core.h" #include "video_core/video_core.h"
namespace VideoCore { namespace VideoCore {
static Common::Vec4f ColorRGBA8(const u32 color) {
const auto rgba =
Common::Vec4u{color >> 0 & 0xFF, color >> 8 & 0xFF, color >> 16 & 0xFF, color >> 24 & 0xFF};
return rgba / 255.0f;
}
static Common::Vec3f LightColor(const Pica::LightingRegs::LightColor& color) {
return Common::Vec3u{color.r, color.g, color.b} / 255.0f;
}
RasterizerAccelerated::RasterizerAccelerated() {
uniform_block_data.lighting_lut_dirty.fill(true);
}
void RasterizerAccelerated::UpdatePagesCachedCount(PAddr addr, u32 size, int delta) { void RasterizerAccelerated::UpdatePagesCachedCount(PAddr addr, u32 size, int delta) {
const u32 page_start = addr >> Memory::CITRA_PAGE_BITS; const u32 page_start = addr >> Memory::CITRA_PAGE_BITS;
const u32 page_end = ((addr + size - 1) >> Memory::CITRA_PAGE_BITS) + 1; const u32 page_end = ((addr + size - 1) >> Memory::CITRA_PAGE_BITS) + 1;
@ -101,4 +116,195 @@ void RasterizerAccelerated::ClearAll(bool flush) {
cached_pages = {}; cached_pages = {};
} }
void RasterizerAccelerated::SyncDepthScale() {
float depth_scale =
Pica::float24::FromRaw(Pica::g_state.regs.rasterizer.viewport_depth_range).ToFloat32();
if (depth_scale != uniform_block_data.data.depth_scale) {
uniform_block_data.data.depth_scale = depth_scale;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncDepthOffset() {
float depth_offset =
Pica::float24::FromRaw(Pica::g_state.regs.rasterizer.viewport_depth_near_plane).ToFloat32();
if (depth_offset != uniform_block_data.data.depth_offset) {
uniform_block_data.data.depth_offset = depth_offset;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncFogColor() {
const auto& regs = Pica::g_state.regs;
uniform_block_data.data.fog_color = {
regs.texturing.fog_color.r.Value() / 255.0f,
regs.texturing.fog_color.g.Value() / 255.0f,
regs.texturing.fog_color.b.Value() / 255.0f,
};
uniform_block_data.dirty = true;
}
void RasterizerAccelerated::SyncProcTexNoise() {
const auto& regs = Pica::g_state.regs.texturing;
uniform_block_data.data.proctex_noise_f = {
Pica::float16::FromRaw(regs.proctex_noise_frequency.u).ToFloat32(),
Pica::float16::FromRaw(regs.proctex_noise_frequency.v).ToFloat32(),
};
uniform_block_data.data.proctex_noise_a = {
regs.proctex_noise_u.amplitude / 4095.0f,
regs.proctex_noise_v.amplitude / 4095.0f,
};
uniform_block_data.data.proctex_noise_p = {
Pica::float16::FromRaw(regs.proctex_noise_u.phase).ToFloat32(),
Pica::float16::FromRaw(regs.proctex_noise_v.phase).ToFloat32(),
};
uniform_block_data.dirty = true;
}
void RasterizerAccelerated::SyncProcTexBias() {
const auto& regs = Pica::g_state.regs.texturing;
uniform_block_data.data.proctex_bias =
Pica::float16::FromRaw(regs.proctex.bias_low | (regs.proctex_lut.bias_high << 8))
.ToFloat32();
uniform_block_data.dirty = true;
}
void RasterizerAccelerated::SyncAlphaTest() {
const auto& regs = Pica::g_state.regs;
if (regs.framebuffer.output_merger.alpha_test.ref != uniform_block_data.data.alphatest_ref) {
uniform_block_data.data.alphatest_ref = regs.framebuffer.output_merger.alpha_test.ref;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncCombinerColor() {
auto combiner_color =
ColorRGBA8(Pica::g_state.regs.texturing.tev_combiner_buffer_color.raw);
if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) {
uniform_block_data.data.tev_combiner_buffer_color = combiner_color;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncTevConstColor(std::size_t stage_index,
const Pica::TexturingRegs::TevStageConfig& tev_stage) {
const auto const_color = ColorRGBA8(tev_stage.const_color);
if (const_color == uniform_block_data.data.const_color[stage_index]) {
return;
}
uniform_block_data.data.const_color[stage_index] = const_color;
uniform_block_data.dirty = true;
}
void RasterizerAccelerated::SyncGlobalAmbient() {
auto color = LightColor(Pica::g_state.regs.lighting.global_ambient);
if (color != uniform_block_data.data.lighting_global_ambient) {
uniform_block_data.data.lighting_global_ambient = color;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncLightSpecular0(int light_index) {
auto color = LightColor(Pica::g_state.regs.lighting.light[light_index].specular_0);
if (color != uniform_block_data.data.light_src[light_index].specular_0) {
uniform_block_data.data.light_src[light_index].specular_0 = color;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncLightSpecular1(int light_index) {
auto color = LightColor(Pica::g_state.regs.lighting.light[light_index].specular_1);
if (color != uniform_block_data.data.light_src[light_index].specular_1) {
uniform_block_data.data.light_src[light_index].specular_1 = color;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncLightDiffuse(int light_index) {
auto color = LightColor(Pica::g_state.regs.lighting.light[light_index].diffuse);
if (color != uniform_block_data.data.light_src[light_index].diffuse) {
uniform_block_data.data.light_src[light_index].diffuse = color;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncLightAmbient(int light_index) {
auto color = LightColor(Pica::g_state.regs.lighting.light[light_index].ambient);
if (color != uniform_block_data.data.light_src[light_index].ambient) {
uniform_block_data.data.light_src[light_index].ambient = color;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncLightPosition(int light_index) {
const Common::Vec3f position = {
Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].x).ToFloat32(),
Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].y).ToFloat32(),
Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].z).ToFloat32()};
if (position != uniform_block_data.data.light_src[light_index].position) {
uniform_block_data.data.light_src[light_index].position = position;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncLightSpotDirection(int light_index) {
const auto& light = Pica::g_state.regs.lighting.light[light_index];
const auto spot_direction = Common::Vec3f{light.spot_x / 2047.0f, light.spot_y / 2047.0f, light.spot_z / 2047.0f};
if (spot_direction != uniform_block_data.data.light_src[light_index].spot_direction) {
uniform_block_data.data.light_src[light_index].spot_direction = spot_direction;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncLightDistanceAttenuationBias(int light_index) {
float dist_atten_bias =
Pica::float20::FromRaw(Pica::g_state.regs.lighting.light[light_index].dist_atten_bias)
.ToFloat32();
if (dist_atten_bias != uniform_block_data.data.light_src[light_index].dist_atten_bias) {
uniform_block_data.data.light_src[light_index].dist_atten_bias = dist_atten_bias;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncLightDistanceAttenuationScale(int light_index) {
float dist_atten_scale =
Pica::float20::FromRaw(Pica::g_state.regs.lighting.light[light_index].dist_atten_scale)
.ToFloat32();
if (dist_atten_scale != uniform_block_data.data.light_src[light_index].dist_atten_scale) {
uniform_block_data.data.light_src[light_index].dist_atten_scale = dist_atten_scale;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncShadowBias() {
const auto& shadow = Pica::g_state.regs.framebuffer.shadow;
float constant = Pica::float16::FromRaw(shadow.constant).ToFloat32();
float linear = Pica::float16::FromRaw(shadow.linear).ToFloat32();
if (constant != uniform_block_data.data.shadow_bias_constant ||
linear != uniform_block_data.data.shadow_bias_linear) {
uniform_block_data.data.shadow_bias_constant = constant;
uniform_block_data.data.shadow_bias_linear = linear;
uniform_block_data.dirty = true;
}
}
void RasterizerAccelerated::SyncShadowTextureBias() {
int bias = Pica::g_state.regs.texturing.shadow.bias << 1;
if (bias != uniform_block_data.data.shadow_texture_bias) {
uniform_block_data.data.shadow_texture_bias = bias;
uniform_block_data.dirty = true;
}
}
} // namespace VideoCore } // namespace VideoCore

View File

@ -3,19 +3,107 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#pragma once #pragma once
#include "common/vector_math.h"
#include "video_core/rasterizer_interface.h" #include "video_core/rasterizer_interface.h"
#include "video_core/regs_texturing.h"
#include "video_core/shader/shader_uniforms.h"
namespace VideoCore { namespace VideoCore {
class RasterizerAccelerated : public RasterizerInterface { class RasterizerAccelerated : public RasterizerInterface {
public: public:
RasterizerAccelerated();
virtual ~RasterizerAccelerated() = default; virtual ~RasterizerAccelerated() = default;
void UpdatePagesCachedCount(PAddr addr, u32 size, int delta) override; void UpdatePagesCachedCount(PAddr addr, u32 size, int delta) override;
void ClearAll(bool flush) override; void ClearAll(bool flush) override;
protected:
/// Syncs the depth scale to match the PICA register
void SyncDepthScale();
/// Syncs the depth offset to match the PICA register
void SyncDepthOffset();
/// Syncs the fog states to match the PICA register
void SyncFogColor();
/// Sync the procedural texture noise configuration to match the PICA register
void SyncProcTexNoise();
/// Sync the procedural texture bias configuration to match the PICA register
void SyncProcTexBias();
/// Syncs the alpha test states to match the PICA register
void SyncAlphaTest();
/// Syncs the TEV combiner color buffer to match the PICA register
void SyncCombinerColor();
/// Syncs the TEV constant color to match the PICA register
void SyncTevConstColor(std::size_t tev_index,
const Pica::TexturingRegs::TevStageConfig& tev_stage);
/// Syncs the lighting global ambient color to match the PICA register
void SyncGlobalAmbient();
/// Syncs the specified light's specular 0 color to match the PICA register
void SyncLightSpecular0(int light_index);
/// Syncs the specified light's specular 1 color to match the PICA register
void SyncLightSpecular1(int light_index);
/// Syncs the specified light's diffuse color to match the PICA register
void SyncLightDiffuse(int light_index);
/// Syncs the specified light's ambient color to match the PICA register
void SyncLightAmbient(int light_index);
/// Syncs the specified light's position to match the PICA register
void SyncLightPosition(int light_index);
/// Syncs the specified spot light direcition to match the PICA register
void SyncLightSpotDirection(int light_index);
/// Syncs the specified light's distance attenuation bias to match the PICA register
void SyncLightDistanceAttenuationBias(int light_index);
/// Syncs the specified light's distance attenuation scale to match the PICA register
void SyncLightDistanceAttenuationScale(int light_index);
/// Syncs the shadow rendering bias to match the PICA register
void SyncShadowBias();
/// Syncs the shadow texture bias to match the PICA register
void SyncShadowTextureBias();
private: private:
struct UniformBlockData {
Pica::Shader::UniformData data{};
std::array<bool, Pica::LightingRegs::NumLightingSampler> lighting_lut_dirty{};
bool lighting_lut_dirty_any = true;
bool fog_lut_dirty = true;
bool proctex_noise_lut_dirty = true;
bool proctex_color_map_dirty = true;
bool proctex_alpha_map_dirty = true;
bool proctex_lut_dirty = true;
bool proctex_diff_lut_dirty = true;
bool dirty = true;
};
protected:
std::array<u16, 0x30000> cached_pages{}; std::array<u16, 0x30000> cached_pages{};
UniformBlockData uniform_block_data{};
std::array<std::array<Common::Vec2f, 256>, Pica::LightingRegs::NumLightingSampler>
lighting_lut_data{};
std::array<Common::Vec2f, 128> fog_lut_data{};
std::array<Common::Vec2f, 128> proctex_noise_lut_data{};
std::array<Common::Vec2f, 128> proctex_color_map_data{};
std::array<Common::Vec2f, 128> proctex_alpha_map_data{};
std::array<Common::Vec4f, 256> proctex_lut_data{};
std::array<Common::Vec4f, 256> proctex_diff_lut_data{};
}; };
} // namespace VideoCore } // namespace VideoCore

View File

@ -71,19 +71,6 @@ RasterizerOpenGL::RasterizerOpenGL(Frontend::EmuWindow& emu_window, Driver& driv
sw_vao.Create(); sw_vao.Create();
hw_vao.Create(); hw_vao.Create();
uniform_block_data.dirty = true;
uniform_block_data.lighting_lut_dirty.fill(true);
uniform_block_data.lighting_lut_dirty_any = true;
uniform_block_data.fog_lut_dirty = true;
uniform_block_data.proctex_noise_lut_dirty = true;
uniform_block_data.proctex_color_map_dirty = true;
uniform_block_data.proctex_alpha_map_dirty = true;
uniform_block_data.proctex_lut_dirty = true;
uniform_block_data.proctex_diff_lut_dirty = true;
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_alignment); glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_alignment);
uniform_size_aligned_vs = uniform_size_aligned_vs =
Common::AlignUp<std::size_t>(sizeof(VSUniformData), uniform_buffer_alignment); Common::AlignUp<std::size_t>(sizeof(VSUniformData), uniform_buffer_alignment);
@ -1653,24 +1640,6 @@ void RasterizerOpenGL::SyncCullMode() {
} }
} }
void RasterizerOpenGL::SyncDepthScale() {
float depth_scale =
Pica::float24::FromRaw(Pica::g_state.regs.rasterizer.viewport_depth_range).ToFloat32();
if (depth_scale != uniform_block_data.data.depth_scale) {
uniform_block_data.data.depth_scale = depth_scale;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncDepthOffset() {
float depth_offset =
Pica::float24::FromRaw(Pica::g_state.regs.rasterizer.viewport_depth_near_plane).ToFloat32();
if (depth_offset != uniform_block_data.data.depth_offset) {
uniform_block_data.data.depth_offset = depth_offset;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncBlendEnabled() { void RasterizerOpenGL::SyncBlendEnabled() {
state.blend.enabled = (Pica::g_state.regs.framebuffer.output_merger.alphablend_enable == 1); state.blend.enabled = (Pica::g_state.regs.framebuffer.output_merger.alphablend_enable == 1);
} }
@ -1700,51 +1669,6 @@ void RasterizerOpenGL::SyncBlendColor() {
state.blend.color.alpha = blend_color[3]; state.blend.color.alpha = blend_color[3];
} }
void RasterizerOpenGL::SyncFogColor() {
const auto& regs = Pica::g_state.regs;
uniform_block_data.data.fog_color = {
regs.texturing.fog_color.r.Value() / 255.0f,
regs.texturing.fog_color.g.Value() / 255.0f,
regs.texturing.fog_color.b.Value() / 255.0f,
};
uniform_block_data.dirty = true;
}
void RasterizerOpenGL::SyncProcTexNoise() {
const auto& regs = Pica::g_state.regs.texturing;
uniform_block_data.data.proctex_noise_f = {
Pica::float16::FromRaw(regs.proctex_noise_frequency.u).ToFloat32(),
Pica::float16::FromRaw(regs.proctex_noise_frequency.v).ToFloat32(),
};
uniform_block_data.data.proctex_noise_a = {
regs.proctex_noise_u.amplitude / 4095.0f,
regs.proctex_noise_v.amplitude / 4095.0f,
};
uniform_block_data.data.proctex_noise_p = {
Pica::float16::FromRaw(regs.proctex_noise_u.phase).ToFloat32(),
Pica::float16::FromRaw(regs.proctex_noise_v.phase).ToFloat32(),
};
uniform_block_data.dirty = true;
}
void RasterizerOpenGL::SyncProcTexBias() {
const auto& regs = Pica::g_state.regs.texturing;
uniform_block_data.data.proctex_bias =
Pica::float16::FromRaw(regs.proctex.bias_low | (regs.proctex_lut.bias_high << 8))
.ToFloat32();
uniform_block_data.dirty = true;
}
void RasterizerOpenGL::SyncAlphaTest() {
const auto& regs = Pica::g_state.regs;
if (regs.framebuffer.output_merger.alpha_test.ref != uniform_block_data.data.alphatest_ref) {
uniform_block_data.data.alphatest_ref = regs.framebuffer.output_merger.alpha_test.ref;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncLogicOp() { void RasterizerOpenGL::SyncLogicOp() {
const auto& regs = Pica::g_state.regs; const auto& regs = Pica::g_state.regs;
state.logic_op = PicaToGL::LogicOp(regs.framebuffer.output_merger.logic_op); state.logic_op = PicaToGL::LogicOp(regs.framebuffer.output_merger.logic_op);
@ -1828,131 +1752,6 @@ void RasterizerOpenGL::SyncDepthTest() {
: GL_ALWAYS; : GL_ALWAYS;
} }
void RasterizerOpenGL::SyncCombinerColor() {
auto combiner_color =
PicaToGL::ColorRGBA8(Pica::g_state.regs.texturing.tev_combiner_buffer_color.raw);
if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) {
uniform_block_data.data.tev_combiner_buffer_color = combiner_color;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncTevConstColor(std::size_t stage_index,
const Pica::TexturingRegs::TevStageConfig& tev_stage) {
const auto const_color = PicaToGL::ColorRGBA8(tev_stage.const_color);
if (const_color == uniform_block_data.data.const_color[stage_index]) {
return;
}
uniform_block_data.data.const_color[stage_index] = const_color;
uniform_block_data.dirty = true;
}
void RasterizerOpenGL::SyncGlobalAmbient() {
auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.global_ambient);
if (color != uniform_block_data.data.lighting_global_ambient) {
uniform_block_data.data.lighting_global_ambient = color;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncLightSpecular0(int light_index) {
auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].specular_0);
if (color != uniform_block_data.data.light_src[light_index].specular_0) {
uniform_block_data.data.light_src[light_index].specular_0 = color;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncLightSpecular1(int light_index) {
auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].specular_1);
if (color != uniform_block_data.data.light_src[light_index].specular_1) {
uniform_block_data.data.light_src[light_index].specular_1 = color;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncLightDiffuse(int light_index) {
auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].diffuse);
if (color != uniform_block_data.data.light_src[light_index].diffuse) {
uniform_block_data.data.light_src[light_index].diffuse = color;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncLightAmbient(int light_index) {
auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].ambient);
if (color != uniform_block_data.data.light_src[light_index].ambient) {
uniform_block_data.data.light_src[light_index].ambient = color;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncLightPosition(int light_index) {
const auto& light = Pica::g_state.regs.lighting.light[light_index];
const Common::Vec3f position = {Pica::float16::FromRaw(light.x).ToFloat32(),
Pica::float16::FromRaw(light.y).ToFloat32(),
Pica::float16::FromRaw(light.z).ToFloat32()};
if (position != uniform_block_data.data.light_src[light_index].position) {
uniform_block_data.data.light_src[light_index].position = position;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncLightSpotDirection(int light_index) {
const auto& light = Pica::g_state.regs.lighting.light[light_index];
const auto spot_direction =
Common::Vec3f{light.spot_x / 2047.0f, light.spot_y / 2047.0f, light.spot_z / 2047.0f};
if (spot_direction != uniform_block_data.data.light_src[light_index].spot_direction) {
uniform_block_data.data.light_src[light_index].spot_direction = spot_direction;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncLightDistanceAttenuationBias(int light_index) {
const auto& light = Pica::g_state.regs.lighting.light[light_index];
float dist_atten_bias = Pica::float20::FromRaw(light.dist_atten_bias).ToFloat32();
if (dist_atten_bias != uniform_block_data.data.light_src[light_index].dist_atten_bias) {
uniform_block_data.data.light_src[light_index].dist_atten_bias = dist_atten_bias;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncLightDistanceAttenuationScale(int light_index) {
const auto& light = Pica::g_state.regs.lighting.light[light_index];
float dist_atten_scale = Pica::float20::FromRaw(light.dist_atten_scale).ToFloat32();
if (dist_atten_scale != uniform_block_data.data.light_src[light_index].dist_atten_scale) {
uniform_block_data.data.light_src[light_index].dist_atten_scale = dist_atten_scale;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncShadowBias() {
const auto& shadow = Pica::g_state.regs.framebuffer.shadow;
GLfloat constant = Pica::float16::FromRaw(shadow.constant).ToFloat32();
GLfloat linear = Pica::float16::FromRaw(shadow.linear).ToFloat32();
if (constant != uniform_block_data.data.shadow_bias_constant ||
linear != uniform_block_data.data.shadow_bias_linear) {
uniform_block_data.data.shadow_bias_constant = constant;
uniform_block_data.data.shadow_bias_linear = linear;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncShadowTextureBias() {
GLint bias = Pica::g_state.regs.texturing.shadow.bias << 1;
if (bias != uniform_block_data.data.shadow_texture_bias) {
uniform_block_data.data.shadow_texture_bias = bias;
uniform_block_data.dirty = true;
}
}
void RasterizerOpenGL::SyncAndUploadLUTsLF() { void RasterizerOpenGL::SyncAndUploadLUTsLF() {
constexpr std::size_t max_size = constexpr std::size_t max_size =
sizeof(Common::Vec2f) * 256 * Pica::LightingRegs::NumLightingSampler + sizeof(Common::Vec2f) * 256 * Pica::LightingRegs::NumLightingSampler +

View File

@ -3,12 +3,10 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#pragma once #pragma once
#include "common/vector_math.h"
#include "core/hw/gpu.h" #include "core/hw/gpu.h"
#include "video_core/pica_types.h" #include "video_core/pica_types.h"
#include "video_core/rasterizer_accelerated.h" #include "video_core/rasterizer_accelerated.h"
#include "video_core/regs_lighting.h"
#include "video_core/regs_texturing.h"
#include "video_core/renderer_opengl/gl_shader_manager.h" #include "video_core/renderer_opengl/gl_shader_manager.h"
#include "video_core/renderer_opengl/gl_state.h" #include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/gl_stream_buffer.h" #include "video_core/renderer_opengl/gl_stream_buffer.h"
@ -133,12 +131,6 @@ private:
/// Syncs the cull mode to match the PICA register /// Syncs the cull mode to match the PICA register
void SyncCullMode(); void SyncCullMode();
/// Syncs the depth scale to match the PICA register
void SyncDepthScale();
/// Syncs the depth offset to match the PICA register
void SyncDepthOffset();
/// Syncs the blend enabled status to match the PICA register /// Syncs the blend enabled status to match the PICA register
void SyncBlendEnabled(); void SyncBlendEnabled();
@ -148,18 +140,6 @@ private:
/// Syncs the blend color to match the PICA register /// Syncs the blend color to match the PICA register
void SyncBlendColor(); void SyncBlendColor();
/// Syncs the fog states to match the PICA register
void SyncFogColor();
/// Sync the procedural texture noise configuration to match the PICA register
void SyncProcTexNoise();
/// Sync the procedural texture bias configuration to match the PICA register
void SyncProcTexBias();
/// Syncs the alpha test states to match the PICA register
void SyncAlphaTest();
/// Syncs the logic op states to match the PICA register /// Syncs the logic op states to match the PICA register
void SyncLogicOp(); void SyncLogicOp();
@ -178,46 +158,6 @@ private:
/// Syncs the depth test states to match the PICA register /// Syncs the depth test states to match the PICA register
void SyncDepthTest(); void SyncDepthTest();
/// Syncs the TEV combiner color buffer to match the PICA register
void SyncCombinerColor();
/// Syncs the TEV constant color to match the PICA register
void SyncTevConstColor(std::size_t tev_index,
const Pica::TexturingRegs::TevStageConfig& tev_stage);
/// Syncs the lighting global ambient color to match the PICA register
void SyncGlobalAmbient();
/// Syncs the specified light's specular 0 color to match the PICA register
void SyncLightSpecular0(int light_index);
/// Syncs the specified light's specular 1 color to match the PICA register
void SyncLightSpecular1(int light_index);
/// Syncs the specified light's diffuse color to match the PICA register
void SyncLightDiffuse(int light_index);
/// Syncs the specified light's ambient color to match the PICA register
void SyncLightAmbient(int light_index);
/// Syncs the specified light's position to match the PICA register
void SyncLightPosition(int light_index);
/// Syncs the specified spot light direcition to match the PICA register
void SyncLightSpotDirection(int light_index);
/// Syncs the specified light's distance attenuation bias to match the PICA register
void SyncLightDistanceAttenuationBias(int light_index);
/// Syncs the specified light's distance attenuation scale to match the PICA register
void SyncLightDistanceAttenuationScale(int light_index);
/// Syncs the shadow rendering bias to match the PICA register
void SyncShadowBias();
/// Syncs the shadow texture bias to match the PICA register
void SyncShadowTextureBias();
/// Syncs and uploads the lighting, fog and proctex LUTs /// Syncs and uploads the lighting, fog and proctex LUTs
void SyncAndUploadLUTs(); void SyncAndUploadLUTs();
void SyncAndUploadLUTsLF(); void SyncAndUploadLUTsLF();
@ -263,19 +203,6 @@ private:
bool is_amd; bool is_amd;
bool shader_dirty = true; bool shader_dirty = true;
struct {
UniformData data;
std::array<bool, Pica::LightingRegs::NumLightingSampler> lighting_lut_dirty;
bool lighting_lut_dirty_any;
bool fog_lut_dirty;
bool proctex_noise_lut_dirty;
bool proctex_color_map_dirty;
bool proctex_alpha_map_dirty;
bool proctex_lut_dirty;
bool proctex_diff_lut_dirty;
bool dirty;
} uniform_block_data = {};
std::unique_ptr<ShaderProgramManager> shader_program_manager; std::unique_ptr<ShaderProgramManager> shader_program_manager;
// They shall be big enough for about one frame. // They shall be big enough for about one frame.
@ -304,15 +231,6 @@ private:
OGLTexture texture_buffer_lut_lf; OGLTexture texture_buffer_lut_lf;
OGLTexture texture_buffer_lut_rg; OGLTexture texture_buffer_lut_rg;
OGLTexture texture_buffer_lut_rgba; OGLTexture texture_buffer_lut_rgba;
std::array<std::array<Common::Vec2f, 256>, Pica::LightingRegs::NumLightingSampler>
lighting_lut_data{};
std::array<Common::Vec2f, 128> fog_lut_data{};
std::array<Common::Vec2f, 128> proctex_noise_lut_data{};
std::array<Common::Vec2f, 128> proctex_color_map_data{};
std::array<Common::Vec2f, 128> proctex_alpha_map_data{};
std::array<Common::Vec4f, 256> proctex_lut_data{};
std::array<Common::Vec4f, 256> proctex_diff_lut_data{};
}; };
} // namespace OpenGL } // namespace OpenGL

View File

@ -132,8 +132,6 @@ RasterizerVulkan::RasterizerVulkan(Frontend::EmuWindow& emu_window, const Instan
null_surface.Transition(vk::ImageLayout::eShaderReadOnlyOptimal, 0, 1); null_surface.Transition(vk::ImageLayout::eShaderReadOnlyOptimal, 0, 1);
null_storage_surface.Transition(vk::ImageLayout::eGeneral, 0, 1); null_storage_surface.Transition(vk::ImageLayout::eGeneral, 0, 1);
uniform_block_data.lighting_lut_dirty.fill(true);
uniform_buffer_alignment = instance.UniformMinAlignment(); uniform_buffer_alignment = instance.UniformMinAlignment();
uniform_size_aligned_vs = uniform_size_aligned_vs =
Common::AlignUp<std::size_t>(sizeof(Pica::Shader::VSUniformData), uniform_buffer_alignment); Common::AlignUp<std::size_t>(sizeof(Pica::Shader::VSUniformData), uniform_buffer_alignment);
@ -1694,26 +1692,6 @@ void RasterizerVulkan::SyncCullMode() {
pipeline_info.rasterization.cull_mode.Assign(regs.rasterizer.cull_mode); pipeline_info.rasterization.cull_mode.Assign(regs.rasterizer.cull_mode);
} }
void RasterizerVulkan::SyncDepthScale() {
float depth_scale =
Pica::float24::FromRaw(Pica::g_state.regs.rasterizer.viewport_depth_range).ToFloat32();
if (depth_scale != uniform_block_data.data.depth_scale) {
uniform_block_data.data.depth_scale = depth_scale;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncDepthOffset() {
float depth_offset =
Pica::float24::FromRaw(Pica::g_state.regs.rasterizer.viewport_depth_near_plane).ToFloat32();
if (depth_offset != uniform_block_data.data.depth_offset) {
uniform_block_data.data.depth_offset = depth_offset;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncBlendEnabled() { void RasterizerVulkan::SyncBlendEnabled() {
pipeline_info.blending.blend_enable.Assign( pipeline_info.blending.blend_enable.Assign(
Pica::g_state.regs.framebuffer.output_merger.alphablend_enable); Pica::g_state.regs.framebuffer.output_merger.alphablend_enable);
@ -1745,51 +1723,6 @@ void RasterizerVulkan::SyncBlendColor() {
}); });
} }
void RasterizerVulkan::SyncFogColor() {
const auto& regs = Pica::g_state.regs;
uniform_block_data.data.fog_color = {
regs.texturing.fog_color.r.Value() / 255.0f,
regs.texturing.fog_color.g.Value() / 255.0f,
regs.texturing.fog_color.b.Value() / 255.0f,
};
uniform_block_data.dirty = true;
}
void RasterizerVulkan::SyncProcTexNoise() {
const auto& regs = Pica::g_state.regs.texturing;
uniform_block_data.data.proctex_noise_f = {
Pica::float16::FromRaw(regs.proctex_noise_frequency.u).ToFloat32(),
Pica::float16::FromRaw(regs.proctex_noise_frequency.v).ToFloat32(),
};
uniform_block_data.data.proctex_noise_a = {
regs.proctex_noise_u.amplitude / 4095.0f,
regs.proctex_noise_v.amplitude / 4095.0f,
};
uniform_block_data.data.proctex_noise_p = {
Pica::float16::FromRaw(regs.proctex_noise_u.phase).ToFloat32(),
Pica::float16::FromRaw(regs.proctex_noise_v.phase).ToFloat32(),
};
uniform_block_data.dirty = true;
}
void RasterizerVulkan::SyncProcTexBias() {
const auto& regs = Pica::g_state.regs.texturing;
uniform_block_data.data.proctex_bias =
Pica::float16::FromRaw(regs.proctex.bias_low | (regs.proctex_lut.bias_high << 8))
.ToFloat32();
uniform_block_data.dirty = true;
}
void RasterizerVulkan::SyncAlphaTest() {
const auto& regs = Pica::g_state.regs;
if (regs.framebuffer.output_merger.alpha_test.ref != uniform_block_data.data.alphatest_ref) {
uniform_block_data.data.alphatest_ref = regs.framebuffer.output_merger.alpha_test.ref;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncLogicOp() { void RasterizerVulkan::SyncLogicOp() {
const auto& regs = Pica::g_state.regs; const auto& regs = Pica::g_state.regs;
pipeline_info.blending.logic_op.Assign(regs.framebuffer.output_merger.logic_op); pipeline_info.blending.logic_op.Assign(regs.framebuffer.output_merger.logic_op);
@ -1846,132 +1779,6 @@ void RasterizerVulkan::SyncDepthTest() {
pipeline_info.depth_stencil.depth_compare_op.Assign(compare_op); pipeline_info.depth_stencil.depth_compare_op.Assign(compare_op);
} }
void RasterizerVulkan::SyncCombinerColor() {
auto combiner_color =
PicaToVK::ColorRGBA8(Pica::g_state.regs.texturing.tev_combiner_buffer_color.raw);
if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) {
uniform_block_data.data.tev_combiner_buffer_color = combiner_color;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncTevConstColor(std::size_t stage_index,
const Pica::TexturingRegs::TevStageConfig& tev_stage) {
const auto const_color = PicaToVK::ColorRGBA8(tev_stage.const_color);
if (const_color == uniform_block_data.data.const_color[stage_index]) {
return;
}
uniform_block_data.data.const_color[stage_index] = const_color;
uniform_block_data.dirty = true;
}
void RasterizerVulkan::SyncGlobalAmbient() {
auto color = PicaToVK::LightColor(Pica::g_state.regs.lighting.global_ambient);
if (color != uniform_block_data.data.lighting_global_ambient) {
uniform_block_data.data.lighting_global_ambient = color;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncLightSpecular0(int light_index) {
auto color = PicaToVK::LightColor(Pica::g_state.regs.lighting.light[light_index].specular_0);
if (color != uniform_block_data.data.light_src[light_index].specular_0) {
uniform_block_data.data.light_src[light_index].specular_0 = color;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncLightSpecular1(int light_index) {
auto color = PicaToVK::LightColor(Pica::g_state.regs.lighting.light[light_index].specular_1);
if (color != uniform_block_data.data.light_src[light_index].specular_1) {
uniform_block_data.data.light_src[light_index].specular_1 = color;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncLightDiffuse(int light_index) {
auto color = PicaToVK::LightColor(Pica::g_state.regs.lighting.light[light_index].diffuse);
if (color != uniform_block_data.data.light_src[light_index].diffuse) {
uniform_block_data.data.light_src[light_index].diffuse = color;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncLightAmbient(int light_index) {
auto color = PicaToVK::LightColor(Pica::g_state.regs.lighting.light[light_index].ambient);
if (color != uniform_block_data.data.light_src[light_index].ambient) {
uniform_block_data.data.light_src[light_index].ambient = color;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncLightPosition(int light_index) {
const Common::Vec3f position = {
Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].x).ToFloat32(),
Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].y).ToFloat32(),
Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].z).ToFloat32()};
if (position != uniform_block_data.data.light_src[light_index].position) {
uniform_block_data.data.light_src[light_index].position = position;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncLightSpotDirection(int light_index) {
const auto& light = Pica::g_state.regs.lighting.light[light_index];
const auto spot_direction = Common::Vec3i{light.spot_x, light.spot_y, light.spot_z} / 2047.0f;
if (spot_direction != uniform_block_data.data.light_src[light_index].spot_direction) {
uniform_block_data.data.light_src[light_index].spot_direction = spot_direction;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncLightDistanceAttenuationBias(int light_index) {
float dist_atten_bias =
Pica::float20::FromRaw(Pica::g_state.regs.lighting.light[light_index].dist_atten_bias)
.ToFloat32();
if (dist_atten_bias != uniform_block_data.data.light_src[light_index].dist_atten_bias) {
uniform_block_data.data.light_src[light_index].dist_atten_bias = dist_atten_bias;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncLightDistanceAttenuationScale(int light_index) {
float dist_atten_scale =
Pica::float20::FromRaw(Pica::g_state.regs.lighting.light[light_index].dist_atten_scale)
.ToFloat32();
if (dist_atten_scale != uniform_block_data.data.light_src[light_index].dist_atten_scale) {
uniform_block_data.data.light_src[light_index].dist_atten_scale = dist_atten_scale;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncShadowBias() {
const auto& shadow = Pica::g_state.regs.framebuffer.shadow;
float constant = Pica::float16::FromRaw(shadow.constant).ToFloat32();
float linear = Pica::float16::FromRaw(shadow.linear).ToFloat32();
if (constant != uniform_block_data.data.shadow_bias_constant ||
linear != uniform_block_data.data.shadow_bias_linear) {
uniform_block_data.data.shadow_bias_constant = constant;
uniform_block_data.data.shadow_bias_linear = linear;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncShadowTextureBias() {
int bias = Pica::g_state.regs.texturing.shadow.bias << 1;
if (bias != uniform_block_data.data.shadow_texture_bias) {
uniform_block_data.data.shadow_texture_bias = bias;
uniform_block_data.dirty = true;
}
}
void RasterizerVulkan::SyncAndUploadLUTsLF() { void RasterizerVulkan::SyncAndUploadLUTsLF() {
constexpr std::size_t max_size = constexpr std::size_t max_size =
sizeof(Common::Vec2f) * 256 * Pica::LightingRegs::NumLightingSampler + sizeof(Common::Vec2f) * 256 * Pica::LightingRegs::NumLightingSampler +

View File

@ -4,16 +4,12 @@
#pragma once #pragma once
#include "common/vector_math.h"
#include "core/hw/gpu.h" #include "core/hw/gpu.h"
#include "video_core/rasterizer_accelerated.h" #include "video_core/rasterizer_accelerated.h"
#include "video_core/regs_lighting.h"
#include "video_core/regs_texturing.h"
#include "video_core/renderer_vulkan/vk_pipeline_cache.h" #include "video_core/renderer_vulkan/vk_pipeline_cache.h"
#include "video_core/renderer_vulkan/vk_stream_buffer.h" #include "video_core/renderer_vulkan/vk_stream_buffer.h"
#include "video_core/renderer_vulkan/vk_texture_runtime.h" #include "video_core/renderer_vulkan/vk_texture_runtime.h"
#include "video_core/shader/shader.h" #include "video_core/shader/shader.h"
#include "video_core/shader/shader_uniforms.h"
namespace Frontend { namespace Frontend {
class EmuWindow; class EmuWindow;
@ -125,12 +121,6 @@ private:
/// Syncs the cull mode to match the PICA register /// Syncs the cull mode to match the PICA register
void SyncCullMode(); void SyncCullMode();
/// Syncs the depth scale to match the PICA register
void SyncDepthScale();
/// Syncs the depth offset to match the PICA register
void SyncDepthOffset();
/// Syncs the blend enabled status to match the PICA register /// Syncs the blend enabled status to match the PICA register
void SyncBlendEnabled(); void SyncBlendEnabled();
@ -140,18 +130,6 @@ private:
/// Syncs the blend color to match the PICA register /// Syncs the blend color to match the PICA register
void SyncBlendColor(); void SyncBlendColor();
/// Syncs the fog states to match the PICA register
void SyncFogColor();
/// Sync the procedural texture noise configuration to match the PICA register
void SyncProcTexNoise();
/// Sync the procedural texture bias configuration to match the PICA register
void SyncProcTexBias();
/// Syncs the alpha test states to match the PICA register
void SyncAlphaTest();
/// Syncs the logic op states to match the PICA register /// Syncs the logic op states to match the PICA register
void SyncLogicOp(); void SyncLogicOp();
@ -170,46 +148,6 @@ private:
/// Syncs the depth test states to match the PICA register /// Syncs the depth test states to match the PICA register
void SyncDepthTest(); void SyncDepthTest();
/// Syncs the TEV combiner color buffer to match the PICA register
void SyncCombinerColor();
/// Syncs the TEV constant color to match the PICA register
void SyncTevConstColor(std::size_t tev_index,
const Pica::TexturingRegs::TevStageConfig& tev_stage);
/// Syncs the lighting global ambient color to match the PICA register
void SyncGlobalAmbient();
/// Syncs the specified light's specular 0 color to match the PICA register
void SyncLightSpecular0(int light_index);
/// Syncs the specified light's specular 1 color to match the PICA register
void SyncLightSpecular1(int light_index);
/// Syncs the specified light's diffuse color to match the PICA register
void SyncLightDiffuse(int light_index);
/// Syncs the specified light's ambient color to match the PICA register
void SyncLightAmbient(int light_index);
/// Syncs the specified light's position to match the PICA register
void SyncLightPosition(int light_index);
/// Syncs the specified spot light direcition to match the PICA register
void SyncLightSpotDirection(int light_index);
/// Syncs the specified light's distance attenuation bias to match the PICA register
void SyncLightDistanceAttenuationBias(int light_index);
/// Syncs the specified light's distance attenuation scale to match the PICA register
void SyncLightDistanceAttenuationScale(int light_index);
/// Syncs the shadow rendering bias to match the PICA register
void SyncShadowBias();
/// Syncs the shadow texture bias to match the PICA register
void SyncShadowTextureBias();
/// Syncs and uploads the lighting, fog and proctex LUTs /// Syncs and uploads the lighting, fog and proctex LUTs
void SyncAndUploadLUTs(); void SyncAndUploadLUTs();
void SyncAndUploadLUTsLF(); void SyncAndUploadLUTsLF();
@ -283,19 +221,6 @@ private:
Surface null_surface; Surface null_surface;
Surface null_storage_surface; Surface null_storage_surface;
struct {
Pica::Shader::UniformData data{};
std::array<bool, Pica::LightingRegs::NumLightingSampler> lighting_lut_dirty{};
bool lighting_lut_dirty_any = true;
bool fog_lut_dirty = true;
bool proctex_noise_lut_dirty = true;
bool proctex_color_map_dirty = true;
bool proctex_alpha_map_dirty = true;
bool proctex_lut_dirty = true;
bool proctex_diff_lut_dirty = true;
bool dirty = true;
} uniform_block_data = {};
std::array<SamplerInfo, 3> texture_samplers; std::array<SamplerInfo, 3> texture_samplers;
SamplerInfo texture_cube_sampler; SamplerInfo texture_cube_sampler;
std::unordered_map<SamplerInfo, vk::Sampler> samplers; std::unordered_map<SamplerInfo, vk::Sampler> samplers;
@ -310,15 +235,6 @@ private:
std::size_t uniform_buffer_alignment; std::size_t uniform_buffer_alignment;
std::size_t uniform_size_aligned_vs; std::size_t uniform_size_aligned_vs;
std::size_t uniform_size_aligned_fs; std::size_t uniform_size_aligned_fs;
std::array<std::array<Common::Vec2f, 256>, Pica::LightingRegs::NumLightingSampler>
lighting_lut_data{};
std::array<Common::Vec2f, 128> fog_lut_data{};
std::array<Common::Vec2f, 128> proctex_noise_lut_data{};
std::array<Common::Vec2f, 128> proctex_color_map_data{};
std::array<Common::Vec2f, 128> proctex_alpha_map_data{};
std::array<Common::Vec4f, 256> proctex_lut_data{};
std::array<Common::Vec4f, 256> proctex_diff_lut_data{};
}; };
} // namespace Vulkan } // namespace Vulkan