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

View File

@@ -29,21 +29,16 @@ union RasterizationState {
BitField<4, 2, Pica::RasterizerRegs::CullMode> cull_mode; BitField<4, 2, Pica::RasterizerRegs::CullMode> cull_mode;
}; };
struct DepthStencilState { union DepthStencilState {
union { u32 value = 0;
u32 value = 0; BitField<0, 1, u32> depth_test_enable;
BitField<0, 1, u32> depth_test_enable; BitField<1, 1, u32> depth_write_enable;
BitField<1, 1, u32> depth_write_enable; BitField<2, 1, u32> stencil_test_enable;
BitField<2, 1, u32> stencil_test_enable; BitField<3, 3, Pica::FramebufferRegs::CompareFunc> depth_compare_op;
BitField<3, 3, Pica::FramebufferRegs::CompareFunc> depth_compare_op; BitField<6, 3, Pica::FramebufferRegs::StencilAction> stencil_fail_op;
BitField<6, 3, Pica::FramebufferRegs::StencilAction> stencil_fail_op; BitField<9, 3, Pica::FramebufferRegs::StencilAction> stencil_pass_op;
BitField<9, 3, Pica::FramebufferRegs::StencilAction> stencil_pass_op; BitField<12, 3, Pica::FramebufferRegs::StencilAction> stencil_depth_fail_op;
BitField<12, 3, Pica::FramebufferRegs::StencilAction> stencil_depth_fail_op; BitField<15, 3, Pica::FramebufferRegs::CompareFunc> stencil_compare_op;
BitField<15, 3, Pica::FramebufferRegs::CompareFunc> stencil_compare_op;
};
u8 stencil_reference;
u8 stencil_compare_mask;
u8 stencil_write_mask;
}; };
union BlendingState { union BlendingState {
@@ -59,6 +54,13 @@ union BlendingState {
BitField<27, 4, Pica::FramebufferRegs::LogicOp> logic_op; 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 { union VertexBinding {
u16 value = 0; u16 value = 0;
BitField<0, 4, u16> binding; BitField<0, 4, u16> binding;
@@ -92,13 +94,14 @@ struct PipelineInfo {
VideoCore::PixelFormat depth_attachment = VideoCore::PixelFormat::D24S8; VideoCore::PixelFormat depth_attachment = VideoCore::PixelFormat::D24S8;
RasterizationState rasterization{}; RasterizationState rasterization{};
DepthStencilState depth_stencil{}; DepthStencilState depth_stencil{};
DynamicState dynamic;
[[nodiscard]] bool IsDepthWriteEnabled() const noexcept { [[nodiscard]] bool IsDepthWriteEnabled() const noexcept {
const bool has_stencil = depth_attachment == VideoCore::PixelFormat::D24S8; const bool has_stencil = depth_attachment == VideoCore::PixelFormat::D24S8;
const bool depth_write = const bool depth_write =
depth_stencil.depth_test_enable && depth_stencil.depth_write_enable; depth_stencil.depth_test_enable && depth_stencil.depth_write_enable;
const bool stencil_write = has_stencil && depth_stencil.stencil_test_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; 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.stride.Assign(offset);
binding_offsets[layout.binding_count++] = array_offset + buffer_offset; binding_offsets[layout.binding_count++] = array_offset + buffer_offset;
ASSERT(buffer_offset + offset <= vertex_size);
vertex_buffer.Commit(buffer_offset + offset); vertex_buffer.Commit(buffer_offset + offset);
// Update the pipeline vertex layout // Update the pipeline vertex layout
@@ -1587,12 +1588,8 @@ void RasterizerVulkan::SyncBlendFuncs() {
} }
void RasterizerVulkan::SyncBlendColor() { void RasterizerVulkan::SyncBlendColor() {
const Common::Vec4f blend_color = const auto& regs = Pica::g_state.regs;
PicaToVK::ColorRGBA8(Pica::g_state.regs.framebuffer.output_merger.blend_const.raw); pipeline_info.dynamic.blend_color = regs.framebuffer.output_merger.blend_const.raw;
scheduler.Record([blend_color](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
render_cmdbuf.setBlendConstants(blend_color.AsArray());
});
} }
void RasterizerVulkan::SyncLogicOp() { void RasterizerVulkan::SyncLogicOp() {
@@ -1608,7 +1605,7 @@ void RasterizerVulkan::SyncColorWriteMask() {
void RasterizerVulkan::SyncStencilWriteMask() { void RasterizerVulkan::SyncStencilWriteMask() {
const auto& regs = Pica::g_state.regs; 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) (regs.framebuffer.framebuffer.allow_depth_stencil_write != 0)
? static_cast<u32>(regs.framebuffer.output_merger.stencil_test.write_mask) ? static_cast<u32>(regs.framebuffer.output_merger.stencil_test.write_mask)
: 0; : 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_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_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_compare_op.Assign(stencil_test.func);
pipeline_info.depth_stencil.stencil_reference = stencil_test.reference_value; pipeline_info.dynamic.stencil_reference = stencil_test.reference_value;
pipeline_info.depth_stencil.stencil_compare_mask = stencil_test.input_mask; pipeline_info.dynamic.stencil_compare_mask = stencil_test.input_mask;
} }
void RasterizerVulkan::SyncDepthTest() { void RasterizerVulkan::SyncDepthTest() {

View File

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

View File

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