renderer_vulkan: Pack PicaFSConfig

* Using bitfields the struct size was reduced from 420 to 190 bytes. which should speed up hashing and copying to the worker thread
This commit is contained in:
GPUCode
2022-10-28 20:38:00 +03:00
parent 81f2a0eaa1
commit ff34287e4b
5 changed files with 183 additions and 177 deletions

View File

@@ -162,8 +162,7 @@ void PipelineCache::BindPipeline(const PipelineInfo& info) {
const u64 info_hash_size = instance.IsExtendedDynamicStateSupported()
? offsetof(PipelineInfo, rasterization)
: offsetof(PipelineInfo, depth_stencil) +
offsetof(DepthStencilState, stencil_reference);
: offsetof(PipelineInfo, dynamic);
u64 info_hash = Common::ComputeHash64(&info, info_hash_size);
u64 pipeline_hash = Common::HashCombine(shader_hash, info_hash);
@@ -234,7 +233,7 @@ void PipelineCache::UseTrivialGeometryShader() {
}
void PipelineCache::UseFragmentShader(const Pica::Regs& regs) {
const PicaFSConfig config = PicaFSConfig::BuildFromRegs(regs);
const PicaFSConfig config{regs};
scheduler.Record([this, config](vk::CommandBuffer, vk::CommandBuffer) {
auto [handle, result] = fragment_shaders.Get(config, vk::ShaderStageFlagBits::eFragment,
@@ -301,23 +300,28 @@ void PipelineCache::ApplyDynamic(const PipelineInfo& info) {
PipelineInfo current = current_info;
scheduler.Record([this, info, is_dirty, current](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
if (info.depth_stencil.stencil_compare_mask !=
current.depth_stencil.stencil_compare_mask ||
if (info.dynamic.stencil_compare_mask !=
current.dynamic.stencil_compare_mask ||
is_dirty) {
render_cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack,
info.depth_stencil.stencil_compare_mask);
info.dynamic.stencil_compare_mask);
}
if (info.depth_stencil.stencil_write_mask != current.depth_stencil.stencil_write_mask ||
if (info.dynamic.stencil_write_mask != current.dynamic.stencil_write_mask ||
is_dirty) {
render_cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFrontAndBack,
info.depth_stencil.stencil_write_mask);
info.dynamic.stencil_write_mask);
}
if (info.depth_stencil.stencil_reference != current.depth_stencil.stencil_reference ||
if (info.dynamic.stencil_reference != current.dynamic.stencil_reference ||
is_dirty) {
render_cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
info.depth_stencil.stencil_reference);
info.dynamic.stencil_reference);
}
if (info.dynamic.blend_color != current.dynamic.blend_color || is_dirty) {
const Common::Vec4f color = PicaToVK::ColorRGBA8(info.dynamic.blend_color);
render_cmdbuf.setBlendConstants(color.AsArray());
}
if (instance.IsExtendedDynamicStateSupported()) {

View File

@@ -29,21 +29,16 @@ union RasterizationState {
BitField<4, 2, Pica::RasterizerRegs::CullMode> cull_mode;
};
struct DepthStencilState {
union {
u32 value = 0;
BitField<0, 1, u32> depth_test_enable;
BitField<1, 1, u32> depth_write_enable;
BitField<2, 1, u32> stencil_test_enable;
BitField<3, 3, Pica::FramebufferRegs::CompareFunc> depth_compare_op;
BitField<6, 3, Pica::FramebufferRegs::StencilAction> stencil_fail_op;
BitField<9, 3, Pica::FramebufferRegs::StencilAction> stencil_pass_op;
BitField<12, 3, Pica::FramebufferRegs::StencilAction> stencil_depth_fail_op;
BitField<15, 3, Pica::FramebufferRegs::CompareFunc> stencil_compare_op;
};
u8 stencil_reference;
u8 stencil_compare_mask;
u8 stencil_write_mask;
union DepthStencilState {
u32 value = 0;
BitField<0, 1, u32> depth_test_enable;
BitField<1, 1, u32> depth_write_enable;
BitField<2, 1, u32> stencil_test_enable;
BitField<3, 3, Pica::FramebufferRegs::CompareFunc> depth_compare_op;
BitField<6, 3, Pica::FramebufferRegs::StencilAction> stencil_fail_op;
BitField<9, 3, Pica::FramebufferRegs::StencilAction> stencil_pass_op;
BitField<12, 3, Pica::FramebufferRegs::StencilAction> stencil_depth_fail_op;
BitField<15, 3, Pica::FramebufferRegs::CompareFunc> stencil_compare_op;
};
union BlendingState {
@@ -59,6 +54,13 @@ union BlendingState {
BitField<27, 4, Pica::FramebufferRegs::LogicOp> logic_op;
};
struct DynamicState {
u32 blend_color = 0;
u8 stencil_reference;
u8 stencil_compare_mask;
u8 stencil_write_mask;
};
union VertexBinding {
u16 value = 0;
BitField<0, 4, u16> binding;
@@ -92,13 +94,14 @@ struct PipelineInfo {
VideoCore::PixelFormat depth_attachment = VideoCore::PixelFormat::D24S8;
RasterizationState rasterization{};
DepthStencilState depth_stencil{};
DynamicState dynamic;
[[nodiscard]] bool IsDepthWriteEnabled() const noexcept {
const bool has_stencil = depth_attachment == VideoCore::PixelFormat::D24S8;
const bool depth_write =
depth_stencil.depth_test_enable && depth_stencil.depth_write_enable;
const bool stencil_write = has_stencil && depth_stencil.stencil_test_enable &&
depth_stencil.stencil_write_mask != 0;
dynamic.stencil_write_mask != 0;
return depth_write || stencil_write;
}

View File

@@ -304,6 +304,7 @@ void RasterizerVulkan::SetupVertexArray(u32 vs_input_size, u32 vs_input_index_mi
binding.stride.Assign(offset);
binding_offsets[layout.binding_count++] = array_offset + buffer_offset;
ASSERT(buffer_offset + offset <= vertex_size);
vertex_buffer.Commit(buffer_offset + offset);
// Update the pipeline vertex layout
@@ -1587,12 +1588,8 @@ void RasterizerVulkan::SyncBlendFuncs() {
}
void RasterizerVulkan::SyncBlendColor() {
const Common::Vec4f blend_color =
PicaToVK::ColorRGBA8(Pica::g_state.regs.framebuffer.output_merger.blend_const.raw);
scheduler.Record([blend_color](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
render_cmdbuf.setBlendConstants(blend_color.AsArray());
});
const auto& regs = Pica::g_state.regs;
pipeline_info.dynamic.blend_color = regs.framebuffer.output_merger.blend_const.raw;
}
void RasterizerVulkan::SyncLogicOp() {
@@ -1608,7 +1605,7 @@ void RasterizerVulkan::SyncColorWriteMask() {
void RasterizerVulkan::SyncStencilWriteMask() {
const auto& regs = Pica::g_state.regs;
pipeline_info.depth_stencil.stencil_write_mask =
pipeline_info.dynamic.stencil_write_mask =
(regs.framebuffer.framebuffer.allow_depth_stencil_write != 0)
? static_cast<u32>(regs.framebuffer.output_merger.stencil_test.write_mask)
: 0;
@@ -1634,8 +1631,8 @@ void RasterizerVulkan::SyncStencilTest() {
pipeline_info.depth_stencil.stencil_pass_op.Assign(stencil_test.action_depth_pass);
pipeline_info.depth_stencil.stencil_depth_fail_op.Assign(stencil_test.action_depth_fail);
pipeline_info.depth_stencil.stencil_compare_op.Assign(stencil_test.func);
pipeline_info.depth_stencil.stencil_reference = stencil_test.reference_value;
pipeline_info.depth_stencil.stencil_compare_mask = stencil_test.input_mask;
pipeline_info.dynamic.stencil_reference = stencil_test.reference_value;
pipeline_info.dynamic.stencil_compare_mask = stencil_test.input_mask;
}
void RasterizerVulkan::SyncDepthTest() {

View File

@@ -8,6 +8,7 @@
#include "common/logging/log.h"
#include "core/core.h"
#include "video_core/pica_state.h"
#include "video_core/regs_framebuffer.h"
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
#include "video_core/renderer_vulkan/vk_shader_gen.h"
#include "video_core/video_core.h"
@@ -99,25 +100,21 @@ out gl_PerVertex {
return out;
}
PicaFSConfig PicaFSConfig::BuildFromRegs(const Pica::Regs& regs) {
PicaFSConfig res{};
PicaFSConfig::PicaFSConfig(const Pica::Regs& regs) {
state.scissor_test_mode.Assign(regs.rasterizer.scissor_test.mode);
auto& state = res.state;
state.depthmap_enable.Assign(regs.rasterizer.depthmap_enable);
state.scissor_test_mode = regs.rasterizer.scissor_test.mode;
state.depthmap_enable = regs.rasterizer.depthmap_enable;
state.alpha_test_func = regs.framebuffer.output_merger.alpha_test.enable
state.alpha_test_func.Assign(regs.framebuffer.output_merger.alpha_test.enable
? regs.framebuffer.output_merger.alpha_test.func.Value()
: FramebufferRegs::CompareFunc::Always;
: FramebufferRegs::CompareFunc::Always);
state.texture0_type = regs.texturing.texture0.type;
state.texture0_type.Assign(regs.texturing.texture0.type);
state.texture2_use_coord1 = regs.texturing.main_config.texture2_use_coord1 != 0;
state.texture2_use_coord1.Assign(regs.texturing.main_config.texture2_use_coord1 != 0);
state.alphablend_enable = {};
state.logic_op = {};
state.alphablend_enable.Assign(0);
state.logic_op.Assign(Pica::FramebufferRegs::LogicOp::Clear);
// Copy relevant tev stages fields.
// We don't sync const_color here because of the high variance, it is a
@@ -132,95 +129,95 @@ PicaFSConfig PicaFSConfig::BuildFromRegs(const Pica::Regs& regs) {
state.tev_stages[i].scales_raw = tev_stage.scales_raw;
}
state.fog_mode = regs.texturing.fog_mode;
state.fog_flip = regs.texturing.fog_flip != 0;
state.fog_mode.Assign(regs.texturing.fog_mode);
state.fog_flip.Assign(regs.texturing.fog_flip != 0);
state.combiner_buffer_input = regs.texturing.tev_combiner_buffer_input.update_mask_rgb.Value() |
state.combiner_buffer_input.Assign(regs.texturing.tev_combiner_buffer_input.update_mask_rgb.Value() |
regs.texturing.tev_combiner_buffer_input.update_mask_a.Value()
<< 4;
<< 4);
// Fragment lighting
state.lighting.enable = !regs.lighting.disable;
state.lighting.src_num = regs.lighting.max_light_index + 1;
state.lighting.enable.Assign(!regs.lighting.disable);
state.lighting.src_num.Assign(regs.lighting.max_light_index + 1);
for (unsigned light_index = 0; light_index < state.lighting.src_num; ++light_index) {
unsigned num = regs.lighting.light_enable.GetNum(light_index);
for (u32 light_index = 0; light_index < state.lighting.src_num; ++light_index) {
u32 num = regs.lighting.light_enable.GetNum(light_index);
const auto& light = regs.lighting.light[num];
state.lighting.light[light_index].num = num;
state.lighting.light[light_index].directional = light.config.directional != 0;
state.lighting.light[light_index].two_sided_diffuse = light.config.two_sided_diffuse != 0;
state.lighting.light[light_index].geometric_factor_0 = light.config.geometric_factor_0 != 0;
state.lighting.light[light_index].geometric_factor_1 = light.config.geometric_factor_1 != 0;
state.lighting.light[light_index].dist_atten_enable =
!regs.lighting.IsDistAttenDisabled(num);
state.lighting.light[light_index].spot_atten_enable =
!regs.lighting.IsSpotAttenDisabled(num);
state.lighting.light[light_index].shadow_enable = !regs.lighting.IsShadowDisabled(num);
state.lighting.light[light_index].num.Assign(num);
state.lighting.light[light_index].directional.Assign(light.config.directional != 0);
state.lighting.light[light_index].two_sided_diffuse.Assign(light.config.two_sided_diffuse != 0);
state.lighting.light[light_index].geometric_factor_0.Assign(light.config.geometric_factor_0 != 0);
state.lighting.light[light_index].geometric_factor_1.Assign(light.config.geometric_factor_1 != 0);
state.lighting.light[light_index].dist_atten_enable.Assign(
!regs.lighting.IsDistAttenDisabled(num));
state.lighting.light[light_index].spot_atten_enable.Assign(
!regs.lighting.IsSpotAttenDisabled(num));
state.lighting.light[light_index].shadow_enable.Assign(!regs.lighting.IsShadowDisabled(num));
}
state.lighting.lut_d0.enable = regs.lighting.config1.disable_lut_d0 == 0;
state.lighting.lut_d0.abs_input = regs.lighting.abs_lut_input.disable_d0 == 0;
state.lighting.lut_d0.type = regs.lighting.lut_input.d0.Value();
state.lighting.lut_d0.enable.Assign(regs.lighting.config1.disable_lut_d0 == 0);
state.lighting.lut_d0.abs_input.Assign(regs.lighting.abs_lut_input.disable_d0 == 0);
state.lighting.lut_d0.type.Assign(regs.lighting.lut_input.d0.Value());
state.lighting.lut_d0.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d0);
state.lighting.lut_d1.enable = regs.lighting.config1.disable_lut_d1 == 0;
state.lighting.lut_d1.abs_input = regs.lighting.abs_lut_input.disable_d1 == 0;
state.lighting.lut_d1.type = regs.lighting.lut_input.d1.Value();
state.lighting.lut_d1.enable.Assign(regs.lighting.config1.disable_lut_d1 == 0);
state.lighting.lut_d1.abs_input.Assign(regs.lighting.abs_lut_input.disable_d1 == 0);
state.lighting.lut_d1.type.Assign(regs.lighting.lut_input.d1.Value());
state.lighting.lut_d1.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d1);
// this is a dummy field due to lack of the corresponding register
state.lighting.lut_sp.enable = true;
state.lighting.lut_sp.abs_input = regs.lighting.abs_lut_input.disable_sp == 0;
state.lighting.lut_sp.type = regs.lighting.lut_input.sp.Value();
state.lighting.lut_sp.enable.Assign(1);
state.lighting.lut_sp.abs_input.Assign(regs.lighting.abs_lut_input.disable_sp == 0);
state.lighting.lut_sp.type.Assign(regs.lighting.lut_input.sp.Value());
state.lighting.lut_sp.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.sp);
state.lighting.lut_fr.enable = regs.lighting.config1.disable_lut_fr == 0;
state.lighting.lut_fr.abs_input = regs.lighting.abs_lut_input.disable_fr == 0;
state.lighting.lut_fr.type = regs.lighting.lut_input.fr.Value();
state.lighting.lut_fr.enable.Assign(regs.lighting.config1.disable_lut_fr == 0);
state.lighting.lut_fr.abs_input.Assign(regs.lighting.abs_lut_input.disable_fr == 0);
state.lighting.lut_fr.type.Assign(regs.lighting.lut_input.fr.Value());
state.lighting.lut_fr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.fr);
state.lighting.lut_rr.enable = regs.lighting.config1.disable_lut_rr == 0;
state.lighting.lut_rr.abs_input = regs.lighting.abs_lut_input.disable_rr == 0;
state.lighting.lut_rr.type = regs.lighting.lut_input.rr.Value();
state.lighting.lut_rr.enable.Assign(regs.lighting.config1.disable_lut_rr == 0);
state.lighting.lut_rr.abs_input.Assign(regs.lighting.abs_lut_input.disable_rr == 0);
state.lighting.lut_rr.type.Assign(regs.lighting.lut_input.rr.Value());
state.lighting.lut_rr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rr);
state.lighting.lut_rg.enable = regs.lighting.config1.disable_lut_rg == 0;
state.lighting.lut_rg.abs_input = regs.lighting.abs_lut_input.disable_rg == 0;
state.lighting.lut_rg.type = regs.lighting.lut_input.rg.Value();
state.lighting.lut_rg.enable.Assign(regs.lighting.config1.disable_lut_rg == 0);
state.lighting.lut_rg.abs_input.Assign(regs.lighting.abs_lut_input.disable_rg == 0);
state.lighting.lut_rg.type.Assign(regs.lighting.lut_input.rg.Value());
state.lighting.lut_rg.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rg);
state.lighting.lut_rb.enable = regs.lighting.config1.disable_lut_rb == 0;
state.lighting.lut_rb.abs_input = regs.lighting.abs_lut_input.disable_rb == 0;
state.lighting.lut_rb.type = regs.lighting.lut_input.rb.Value();
state.lighting.lut_rb.enable.Assign(regs.lighting.config1.disable_lut_rb == 0);
state.lighting.lut_rb.abs_input.Assign(regs.lighting.abs_lut_input.disable_rb == 0);
state.lighting.lut_rb.type.Assign(regs.lighting.lut_input.rb.Value());
state.lighting.lut_rb.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rb);
state.lighting.config = regs.lighting.config0.config;
state.lighting.enable_primary_alpha = regs.lighting.config0.enable_primary_alpha;
state.lighting.enable_secondary_alpha = regs.lighting.config0.enable_secondary_alpha;
state.lighting.bump_mode = regs.lighting.config0.bump_mode;
state.lighting.bump_selector = regs.lighting.config0.bump_selector;
state.lighting.bump_renorm = regs.lighting.config0.disable_bump_renorm == 0;
state.lighting.clamp_highlights = regs.lighting.config0.clamp_highlights != 0;
state.lighting.config.Assign(regs.lighting.config0.config);
state.lighting.enable_primary_alpha.Assign(regs.lighting.config0.enable_primary_alpha);
state.lighting.enable_secondary_alpha.Assign(regs.lighting.config0.enable_secondary_alpha);
state.lighting.bump_mode.Assign(regs.lighting.config0.bump_mode);
state.lighting.bump_selector.Assign(regs.lighting.config0.bump_selector);
state.lighting.bump_renorm.Assign(regs.lighting.config0.disable_bump_renorm == 0);
state.lighting.clamp_highlights.Assign(regs.lighting.config0.clamp_highlights != 0);
state.lighting.enable_shadow = regs.lighting.config0.enable_shadow != 0;
state.lighting.shadow_primary = regs.lighting.config0.shadow_primary != 0;
state.lighting.shadow_secondary = regs.lighting.config0.shadow_secondary != 0;
state.lighting.shadow_invert = regs.lighting.config0.shadow_invert != 0;
state.lighting.shadow_alpha = regs.lighting.config0.shadow_alpha != 0;
state.lighting.shadow_selector = regs.lighting.config0.shadow_selector;
state.lighting.enable_shadow.Assign(regs.lighting.config0.enable_shadow != 0);
state.lighting.shadow_primary.Assign(regs.lighting.config0.shadow_primary != 0);
state.lighting.shadow_secondary.Assign(regs.lighting.config0.shadow_secondary != 0);
state.lighting.shadow_invert.Assign(regs.lighting.config0.shadow_invert != 0);
state.lighting.shadow_alpha.Assign(regs.lighting.config0.shadow_alpha != 0);
state.lighting.shadow_selector.Assign(regs.lighting.config0.shadow_selector);
state.proctex.enable = regs.texturing.main_config.texture3_enable;
state.proctex.enable.Assign(regs.texturing.main_config.texture3_enable);
if (state.proctex.enable) {
state.proctex.coord = regs.texturing.main_config.texture3_coordinates;
state.proctex.u_clamp = regs.texturing.proctex.u_clamp;
state.proctex.v_clamp = regs.texturing.proctex.v_clamp;
state.proctex.color_combiner = regs.texturing.proctex.color_combiner;
state.proctex.alpha_combiner = regs.texturing.proctex.alpha_combiner;
state.proctex.separate_alpha = regs.texturing.proctex.separate_alpha;
state.proctex.noise_enable = regs.texturing.proctex.noise_enable;
state.proctex.u_shift = regs.texturing.proctex.u_shift;
state.proctex.v_shift = regs.texturing.proctex.v_shift;
state.proctex.coord.Assign(regs.texturing.main_config.texture3_coordinates);
state.proctex.u_clamp.Assign(regs.texturing.proctex.u_clamp);
state.proctex.v_clamp.Assign(regs.texturing.proctex.v_clamp);
state.proctex.color_combiner.Assign(regs.texturing.proctex.color_combiner);
state.proctex.alpha_combiner.Assign(regs.texturing.proctex.alpha_combiner);
state.proctex.separate_alpha.Assign(regs.texturing.proctex.separate_alpha);
state.proctex.noise_enable.Assign(regs.texturing.proctex.noise_enable);
state.proctex.u_shift.Assign(regs.texturing.proctex.u_shift);
state.proctex.v_shift.Assign(regs.texturing.proctex.v_shift);
state.proctex.lut_width = regs.texturing.proctex_lut.width;
state.proctex.lut_offset0 = regs.texturing.proctex_lut_offset.level0;
state.proctex.lut_offset1 = regs.texturing.proctex_lut_offset.level1;
@@ -228,17 +225,16 @@ PicaFSConfig PicaFSConfig::BuildFromRegs(const Pica::Regs& regs) {
state.proctex.lut_offset3 = regs.texturing.proctex_lut_offset.level3;
state.proctex.lod_min = regs.texturing.proctex_lut.lod_min;
state.proctex.lod_max = regs.texturing.proctex_lut.lod_max;
state.proctex.lut_filter = regs.texturing.proctex_lut.filter;
state.proctex.lut_filter.Assign(regs.texturing.proctex_lut.filter);
}
state.shadow_rendering = regs.framebuffer.output_merger.fragment_operation_mode ==
FramebufferRegs::FragmentOperationMode::Shadow;
state.shadow_rendering.Assign(regs.framebuffer.output_merger.fragment_operation_mode ==
FramebufferRegs::FragmentOperationMode::Shadow);
state.shadow_texture_orthographic = regs.texturing.shadow.orthographic != 0;
return res;
state.shadow_texture_orthographic.Assign(regs.texturing.shadow.orthographic != 0);
}
void PicaShaderConfigCommon::Init(const Pica::ShaderRegs& regs, Pica::Shader::ShaderSetup& setup) {
program_hash = setup.GetProgramCodeHash();
swizzle_hash = setup.GetSwizzleDataHash();

View File

@@ -42,77 +42,85 @@ struct TevStageConfigRaw {
};
struct PicaFSConfigState {
Pica::FramebufferRegs::CompareFunc alpha_test_func;
Pica::RasterizerRegs::ScissorMode scissor_test_mode;
Pica::TexturingRegs::TextureConfig::TextureType texture0_type;
bool texture2_use_coord1;
std::array<TevStageConfigRaw, 6> tev_stages;
u8 combiner_buffer_input;
union {
BitField<0, 3, Pica::FramebufferRegs::CompareFunc> alpha_test_func;
BitField<3, 2, Pica::RasterizerRegs::ScissorMode> scissor_test_mode;
BitField<5, 3, Pica::TexturingRegs::TextureConfig::TextureType> texture0_type;
BitField<8, 1, u32> texture2_use_coord1;
BitField<9, 8, u32> combiner_buffer_input;
BitField<17, 1, Pica::RasterizerRegs::DepthBuffering> depthmap_enable;
BitField<18, 3, Pica::TexturingRegs::FogMode> fog_mode;
BitField<21, 1, u32> fog_flip;
BitField<22, 1, u32> alphablend_enable;
BitField<23, 4, Pica::FramebufferRegs::LogicOp> logic_op;
BitField<27, 1, u32> shadow_rendering;
BitField<28, 1, u32> shadow_texture_orthographic;
};
Pica::RasterizerRegs::DepthBuffering depthmap_enable;
Pica::TexturingRegs::FogMode fog_mode;
bool fog_flip;
bool alphablend_enable;
Pica::FramebufferRegs::LogicOp logic_op;
std::array<TevStageConfigRaw, 6> tev_stages;
struct {
struct {
unsigned num;
bool directional;
bool two_sided_diffuse;
bool dist_atten_enable;
bool spot_atten_enable;
bool geometric_factor_0;
bool geometric_factor_1;
bool shadow_enable;
union {
BitField<0, 3, u16> num;
BitField<3, 1, u16> directional;
BitField<4, 1, u16> two_sided_diffuse;
BitField<5, 1, u16> dist_atten_enable;
BitField<6, 1, u16> spot_atten_enable;
BitField<7, 1, u16> geometric_factor_0;
BitField<8, 1, u16> geometric_factor_1;
BitField<9, 1, u16> shadow_enable;
} light[8];
bool enable;
unsigned src_num;
Pica::LightingRegs::LightingBumpMode bump_mode;
unsigned bump_selector;
bool bump_renorm;
bool clamp_highlights;
Pica::LightingRegs::LightingConfig config;
bool enable_primary_alpha;
bool enable_secondary_alpha;
bool enable_shadow;
bool shadow_primary;
bool shadow_secondary;
bool shadow_invert;
bool shadow_alpha;
unsigned shadow_selector;
union {
BitField<0, 1, u32> enable;
BitField<1, 4, u32> src_num;
BitField<5, 2, Pica::LightingRegs::LightingBumpMode> bump_mode;
BitField<7, 2, u32> bump_selector;
BitField<9, 1, u32> bump_renorm;
BitField<10, 1, u32> clamp_highlights;
BitField<11, 4, Pica::LightingRegs::LightingConfig> config;
BitField<15, 1, u32> enable_primary_alpha;
BitField<16, 1, u32> enable_secondary_alpha;
BitField<17, 1, u32> enable_shadow;
BitField<18, 1, u32> shadow_primary;
BitField<19, 1, u32> shadow_secondary;
BitField<20, 1, u32> shadow_invert;
BitField<21, 1, u32> shadow_alpha;
BitField<22, 2, u32> shadow_selector;
};
struct {
bool enable;
bool abs_input;
Pica::LightingRegs::LightingLutInput type;
union {
BitField<0, 1, u32> enable;
BitField<1, 1, u32> abs_input;
BitField<2, 3, Pica::LightingRegs::LightingLutInput> type;
};
float scale;
} lut_d0, lut_d1, lut_sp, lut_fr, lut_rr, lut_rg, lut_rb;
} lighting;
struct {
bool enable;
u32 coord;
Pica::TexturingRegs::ProcTexClamp u_clamp, v_clamp;
Pica::TexturingRegs::ProcTexCombiner color_combiner, alpha_combiner;
bool separate_alpha;
bool noise_enable;
Pica::TexturingRegs::ProcTexShift u_shift, v_shift;
u32 lut_width;
u32 lut_offset0;
u32 lut_offset1;
u32 lut_offset2;
u32 lut_offset3;
u32 lod_min;
u32 lod_max;
Pica::TexturingRegs::ProcTexFilter lut_filter;
union {
BitField<0, 1, u32> enable;
BitField<1, 2, u32> coord;
BitField<3, 3, Pica::TexturingRegs::ProcTexClamp> u_clamp;
BitField<6, 3, Pica::TexturingRegs::ProcTexClamp> v_clamp;
BitField<9, 4, Pica::TexturingRegs::ProcTexCombiner> color_combiner;
BitField<13, 4, Pica::TexturingRegs::ProcTexCombiner> alpha_combiner;
BitField<17, 3, Pica::TexturingRegs::ProcTexFilter> lut_filter;
BitField<20, 1, u32> separate_alpha;
BitField<21, 1, u32> noise_enable;
BitField<22, 2, Pica::TexturingRegs::ProcTexShift> u_shift;
BitField<24, 2, Pica::TexturingRegs::ProcTexShift> v_shift;
};
u8 lut_width;
u8 lut_offset0;
u8 lut_offset1;
u8 lut_offset2;
u8 lut_offset3;
u8 lod_min;
u8 lod_max;
} proctex;
bool shadow_rendering;
bool shadow_texture_orthographic;
};
/**
@@ -124,9 +132,7 @@ struct PicaFSConfigState {
* two separate shaders sharing the same key.
*/
struct PicaFSConfig : Common::HashableStruct<PicaFSConfigState> {
/// Construct a PicaFSConfig with the given Pica register configuration.
static PicaFSConfig BuildFromRegs(const Pica::Regs& regs);
PicaFSConfig(const Pica::Regs& regs);
bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const {
return (stage_index < 4) && (state.combiner_buffer_input & (1 << stage_index));