mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-23 12:26:56 +02:00
gpu: implement polygon offset
Co-authored-by: Pouare514 <julienaulycee@gmail.com>
This commit is contained in:
@@ -18,7 +18,9 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <bit>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#define KYTY_HW_CTX_PARSER_ARGS \
|
||||
@@ -895,23 +897,44 @@ KYTY_HW_CTX_PARSER(HwCtxSetModeControl) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void HwCtxIgnorePolyOffsetRegister(uint32_t cmd_offset, uint32_t value) {
|
||||
static std::atomic<uint32_t> log_count = 0;
|
||||
static void HwCtxSetPolyOffsetRegister(CommandProcessor& cp, uint32_t cmd_offset, uint32_t value) {
|
||||
HW::PolyOffset offset = cp.GetCtx().GetPolyOffset();
|
||||
|
||||
auto count = log_count.fetch_add(1);
|
||||
if (count < 8) {
|
||||
LOGF_COLOR(Log::Color::Red,
|
||||
"\t temporary: ignoring polygon offset context register 0x%03" PRIx32
|
||||
" = 0x%08" PRIx32 " (depth bias not implemented)\n",
|
||||
cmd_offset, value);
|
||||
switch (cmd_offset) {
|
||||
case Pm4::PA_SU_POLY_OFFSET_DB_FMT_CNTL: {
|
||||
const auto neg_bits =
|
||||
KYTY_PM4_GET(value, PA_SU_POLY_OFFSET_DB_FMT_CNTL, NEG_NUM_DB_BITS);
|
||||
offset.neg_num_db_bits = std::bit_cast<int8_t>(static_cast<uint8_t>(neg_bits));
|
||||
offset.db_is_float_fmt =
|
||||
KYTY_PM4_GET(value, PA_SU_POLY_OFFSET_DB_FMT_CNTL, DB_IS_FLOAT_FMT) != 0;
|
||||
break;
|
||||
}
|
||||
case Pm4::PA_SU_POLY_OFFSET_CLAMP: offset.clamp = std::bit_cast<float>(value); break;
|
||||
case Pm4::PA_SU_POLY_OFFSET_FRONT_SCALE:
|
||||
offset.front_scale = std::bit_cast<float>(value);
|
||||
break;
|
||||
case Pm4::PA_SU_POLY_OFFSET_FRONT_OFFSET:
|
||||
offset.front_offset = std::bit_cast<float>(value);
|
||||
break;
|
||||
case Pm4::PA_SU_POLY_OFFSET_BACK_SCALE:
|
||||
offset.back_scale = std::bit_cast<float>(value);
|
||||
break;
|
||||
case Pm4::PA_SU_POLY_OFFSET_BACK_OFFSET:
|
||||
offset.back_offset = std::bit_cast<float>(value);
|
||||
break;
|
||||
default:
|
||||
EXIT("unknown polygon offset context register 0x%03" PRIx32 " = 0x%08" PRIx32 "\n",
|
||||
cmd_offset, value);
|
||||
}
|
||||
|
||||
cp.GetCtx().SetPolyOffset(offset);
|
||||
}
|
||||
|
||||
KYTY_HW_CTX_PARSER(HwCtxSetPolyOffsetRegisters) {
|
||||
auto num_values = KYTY_PM4_LEN(cmd_id) - 2u;
|
||||
|
||||
for (uint32_t i = 0; i < num_values; i++) {
|
||||
HwCtxIgnorePolyOffsetRegister(cmd_offset + i, buffer[i]);
|
||||
HwCtxSetPolyOffsetRegister(cp, cmd_offset + i, buffer[i]);
|
||||
}
|
||||
|
||||
return num_values;
|
||||
@@ -3705,22 +3728,22 @@ void GraphicsInitJmpTablesCxIndirect() {
|
||||
};
|
||||
|
||||
g_hw_ctx_indirect_func[Pm4::PA_SU_POLY_OFFSET_DB_FMT_CNTL] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
||||
HwCtxIgnorePolyOffsetRegister(cmd_offset, value);
|
||||
HwCtxSetPolyOffsetRegister(cp, cmd_offset, value);
|
||||
};
|
||||
g_hw_ctx_indirect_func[Pm4::PA_SU_POLY_OFFSET_CLAMP] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
||||
HwCtxIgnorePolyOffsetRegister(cmd_offset, value);
|
||||
HwCtxSetPolyOffsetRegister(cp, cmd_offset, value);
|
||||
};
|
||||
g_hw_ctx_indirect_func[Pm4::PA_SU_POLY_OFFSET_FRONT_SCALE] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
||||
HwCtxIgnorePolyOffsetRegister(cmd_offset, value);
|
||||
HwCtxSetPolyOffsetRegister(cp, cmd_offset, value);
|
||||
};
|
||||
g_hw_ctx_indirect_func[Pm4::PA_SU_POLY_OFFSET_FRONT_OFFSET] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
||||
HwCtxIgnorePolyOffsetRegister(cmd_offset, value);
|
||||
HwCtxSetPolyOffsetRegister(cp, cmd_offset, value);
|
||||
};
|
||||
g_hw_ctx_indirect_func[Pm4::PA_SU_POLY_OFFSET_BACK_SCALE] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
||||
HwCtxIgnorePolyOffsetRegister(cmd_offset, value);
|
||||
HwCtxSetPolyOffsetRegister(cp, cmd_offset, value);
|
||||
};
|
||||
g_hw_ctx_indirect_func[Pm4::PA_SU_POLY_OFFSET_BACK_OFFSET] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
||||
HwCtxIgnorePolyOffsetRegister(cmd_offset, value);
|
||||
HwCtxSetPolyOffsetRegister(cp, cmd_offset, value);
|
||||
};
|
||||
|
||||
g_hw_ctx_indirect_func[Pm4::DB_Z_INFO] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
||||
|
||||
@@ -348,6 +348,16 @@ struct ModeControl {
|
||||
bool persp_corr_dis = false;
|
||||
};
|
||||
|
||||
struct PolyOffset {
|
||||
int8_t neg_num_db_bits = -23;
|
||||
bool db_is_float_fmt = true;
|
||||
float clamp = 0.0f;
|
||||
float front_scale = 0.0f;
|
||||
float front_offset = 0.0f;
|
||||
float back_scale = 0.0f;
|
||||
float back_offset = 0.0f;
|
||||
};
|
||||
|
||||
struct BlendControl {
|
||||
uint8_t color_srcblend = 1;
|
||||
uint8_t color_comb_fcn = 0;
|
||||
@@ -905,6 +915,8 @@ public:
|
||||
void SetDepthControl(const DepthControl& control) { m_depth_control = control; }
|
||||
[[nodiscard]] const ModeControl& GetModeControl() const { return m_mode_control; }
|
||||
void SetModeControl(const ModeControl& control) { m_mode_control = control; }
|
||||
[[nodiscard]] const PolyOffset& GetPolyOffset() const { return m_poly_offset; }
|
||||
void SetPolyOffset(const PolyOffset& offset) { m_poly_offset = offset; }
|
||||
[[nodiscard]] const EqaaControl& GetEqaaControl() const { return m_eqaa_control; }
|
||||
void SetEqaaControl(const EqaaControl& control) { m_eqaa_control = control; }
|
||||
[[nodiscard]] const StencilControl& GetStencilControl() const { return m_stencil_control; }
|
||||
@@ -1002,6 +1014,7 @@ private:
|
||||
uint8_t m_stencil_clear_value = 0;
|
||||
|
||||
ModeControl m_mode_control;
|
||||
PolyOffset m_poly_offset;
|
||||
EqaaControl m_eqaa_control;
|
||||
|
||||
ShaderRegisters m_sh_regs;
|
||||
|
||||
@@ -578,24 +578,28 @@ constexpr uint32_t DB_HTILE_SURFACE_PREFETCH_HEIGHT_MASK = 0x3F;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_DST_OUTSIDE_ZERO_TO_ONE_SHIFT = 16;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_DST_OUTSIDE_ZERO_TO_ONE_MASK = 0x1;
|
||||
|
||||
constexpr uint32_t DB_SRESULTS_COMPARE_STATE0 = 0x2B0;
|
||||
constexpr uint32_t DB_SRESULTS_COMPARE_STATE1 = 0x2B1;
|
||||
constexpr uint32_t VGT_GS_MAX_VERT_OUT = 0x2CE;
|
||||
constexpr uint32_t GE_NGG_SUBGRP_CNTL = 0x2D3;
|
||||
constexpr uint32_t VGT_TESS_DISTRIBUTION = 0x2D4;
|
||||
constexpr uint32_t VGT_SHADER_STAGES_EN = 0x2D5;
|
||||
constexpr uint32_t VGT_LS_HS_CONFIG = 0x2D6;
|
||||
constexpr uint32_t VGT_TF_PARAM = 0x2DB;
|
||||
constexpr uint32_t DB_ALPHA_TO_MASK = 0x2DC;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_DB_FMT_CNTL = 0x2DE;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_CLAMP = 0x2DF;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_FRONT_SCALE = 0x2E0;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_FRONT_OFFSET = 0x2E1;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_BACK_SCALE = 0x2E2;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_BACK_OFFSET = 0x2E3;
|
||||
constexpr uint32_t VGT_GS_INSTANCE_CNT = 0x2E4;
|
||||
constexpr uint32_t PA_SC_CENTROID_PRIORITY_0 = 0x2F5;
|
||||
constexpr uint32_t PA_SC_CENTROID_PRIORITY_1 = 0x2F6;
|
||||
constexpr uint32_t DB_SRESULTS_COMPARE_STATE0 = 0x2B0;
|
||||
constexpr uint32_t DB_SRESULTS_COMPARE_STATE1 = 0x2B1;
|
||||
constexpr uint32_t VGT_GS_MAX_VERT_OUT = 0x2CE;
|
||||
constexpr uint32_t GE_NGG_SUBGRP_CNTL = 0x2D3;
|
||||
constexpr uint32_t VGT_TESS_DISTRIBUTION = 0x2D4;
|
||||
constexpr uint32_t VGT_SHADER_STAGES_EN = 0x2D5;
|
||||
constexpr uint32_t VGT_LS_HS_CONFIG = 0x2D6;
|
||||
constexpr uint32_t VGT_TF_PARAM = 0x2DB;
|
||||
constexpr uint32_t DB_ALPHA_TO_MASK = 0x2DC;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_DB_FMT_CNTL = 0x2DE;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_DB_FMT_CNTL_NEG_NUM_DB_BITS_SHIFT = 0;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_DB_FMT_CNTL_NEG_NUM_DB_BITS_MASK = 0xFF;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_DB_FMT_CNTL_DB_IS_FLOAT_FMT_SHIFT = 8;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_DB_FMT_CNTL_DB_IS_FLOAT_FMT_MASK = 0x1;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_CLAMP = 0x2DF;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_FRONT_SCALE = 0x2E0;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_FRONT_OFFSET = 0x2E1;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_BACK_SCALE = 0x2E2;
|
||||
constexpr uint32_t PA_SU_POLY_OFFSET_BACK_OFFSET = 0x2E3;
|
||||
constexpr uint32_t VGT_GS_INSTANCE_CNT = 0x2E4;
|
||||
constexpr uint32_t PA_SC_CENTROID_PRIORITY_0 = 0x2F5;
|
||||
constexpr uint32_t PA_SC_CENTROID_PRIORITY_1 = 0x2F6;
|
||||
|
||||
constexpr uint32_t PA_SC_AA_CONFIG = 0x2F8;
|
||||
constexpr uint32_t PA_SC_AA_CONFIG_MSAA_NUM_SAMPLES_SHIFT = 0;
|
||||
|
||||
@@ -686,14 +686,6 @@ static void McCheck(const HW::ModeControl& c) {
|
||||
}
|
||||
EXIT_NOT_IMPLEMENTED(c.polymode_front_ptype != 0 && c.polymode_front_ptype != 2);
|
||||
EXIT_NOT_IMPLEMENTED(c.polymode_back_ptype != 0 && c.polymode_back_ptype != 2);
|
||||
if (c.poly_offset_front_enable || c.poly_offset_back_enable) {
|
||||
static bool logged = false;
|
||||
if (!logged) {
|
||||
LOGF("\t temporary: PA_SU_SC_MODE_CNTL.POLY_OFFSET_*_ENABLE is not implemented; "
|
||||
"continuing without depth bias\n");
|
||||
logged = true;
|
||||
}
|
||||
}
|
||||
if (c.vtx_window_offset_enable) {
|
||||
static bool logged = false;
|
||||
if (!logged) {
|
||||
|
||||
@@ -947,6 +947,8 @@ void CreatePipelineInternal(
|
||||
vk::DynamicState::eViewport,
|
||||
vk::DynamicState::eScissor,
|
||||
vk::DynamicState::eLineWidth,
|
||||
vk::DynamicState::eDepthBiasEnable,
|
||||
vk::DynamicState::eDepthBias,
|
||||
vk::DynamicState::eStencilCompareMask,
|
||||
vk::DynamicState::eStencilReference,
|
||||
vk::DynamicState::eStencilWriteMask,
|
||||
|
||||
@@ -64,12 +64,32 @@ int32_t ResolveVertexOffset(uint32_t index_offset, const ShaderVertexInputInfo&
|
||||
return 0;
|
||||
}
|
||||
|
||||
static std::atomic<uint32_t> g_draw_state_log_count = 0;
|
||||
static std::atomic<uint32_t> g_draw_input_log_count = 0;
|
||||
static std::atomic<uint32_t> g_mrt_state_log_count = 0;
|
||||
static std::atomic<uint32_t> g_shader_stage_log_count = 0;
|
||||
static std::atomic<uint32_t> g_draw_state_log_count = 0;
|
||||
static std::atomic<uint32_t> g_draw_input_log_count = 0;
|
||||
static std::atomic<uint32_t> g_mrt_state_log_count = 0;
|
||||
static std::atomic<uint32_t> g_shader_stage_log_count = 0;
|
||||
|
||||
static std::atomic<uint32_t> g_framebuffer_skip_log_count = 0;
|
||||
|
||||
static float ConvertPolygonOffsetConstantFactor(float guest_factor, const HW::PolyOffset& offset,
|
||||
vk::Format host_depth_format) {
|
||||
if (offset.db_is_float_fmt) {
|
||||
return guest_factor;
|
||||
}
|
||||
|
||||
int host_depth_bits = 0;
|
||||
switch (host_depth_format) {
|
||||
case vk::Format::eD16Unorm:
|
||||
case vk::Format::eD16UnormS8Uint: host_depth_bits = 16; break;
|
||||
case vk::Format::eD24UnormS8Uint: host_depth_bits = 24; break;
|
||||
default:
|
||||
// A fixed-point guest bias cannot be represented exactly by a floating-point host
|
||||
// attachment without VK_EXT_depth_bias_control.
|
||||
return guest_factor;
|
||||
}
|
||||
return std::ldexp(guest_factor, host_depth_bits + offset.neg_num_db_bits);
|
||||
}
|
||||
|
||||
static const char* RenderColorTypeName(RenderColorType type) {
|
||||
switch (type) {
|
||||
case RenderColorType::NoColorOutput: return "NoColorOutput";
|
||||
@@ -335,6 +355,22 @@ static PipelineDynamicParameters BuildGraphicsDynamicParams(const RenderCommandB
|
||||
ret.stencil_front = depth.stencil_dynamic_front;
|
||||
ret.stencil_back = depth.stencil_dynamic_back;
|
||||
|
||||
const auto& mode = ctx.GetModeControl();
|
||||
const auto& poly_offset = ctx.GetPolyOffset();
|
||||
const bool use_front = mode.poly_offset_front_enable && !mode.cull_front;
|
||||
const bool use_back = mode.poly_offset_back_enable && !mode.cull_back;
|
||||
ret.depth_bias_enable = use_front || use_back;
|
||||
if (ret.depth_bias_enable) {
|
||||
// Vulkan has one bias for both faces. Prefer a visible front face when both are enabled.
|
||||
const float guest_constant_factor =
|
||||
use_front ? poly_offset.front_offset : poly_offset.back_offset;
|
||||
ret.depth_bias_constant_factor =
|
||||
ConvertPolygonOffsetConstantFactor(guest_constant_factor, poly_offset, depth.format);
|
||||
ret.depth_bias_clamp = poly_offset.clamp;
|
||||
ret.depth_bias_slope_factor =
|
||||
(use_front ? poly_offset.front_scale : poly_offset.back_scale) / 16.0f;
|
||||
}
|
||||
|
||||
// CB_COLOR_CONTROL.operation controls special CB operations, not the normal color component
|
||||
// write mask. Use CB_TARGET_MASK here so scanout passes with mode=Disable do not go black.
|
||||
for (uint32_t i = 0; i < RENDER_COLOR_ATTACHMENTS_MAX; i++) {
|
||||
@@ -379,6 +415,13 @@ static void SetDynamicParams(const RenderCommandBuffer& buffer, vk::CommandBuffe
|
||||
}
|
||||
vk_buffer.setLineWidth(line_width);
|
||||
|
||||
vk_buffer.setDepthBiasEnable(dynamic_params.depth_bias_enable ? VK_TRUE : VK_FALSE);
|
||||
if (dynamic_params.depth_bias_enable) {
|
||||
vk_buffer.setDepthBias(dynamic_params.depth_bias_constant_factor,
|
||||
dynamic_params.depth_bias_clamp,
|
||||
dynamic_params.depth_bias_slope_factor);
|
||||
}
|
||||
|
||||
if (dynamic_params.stencil_test_enable) {
|
||||
vk_buffer.setStencilCompareMask(vk::StencilFaceFlagBits::eFront,
|
||||
dynamic_params.stencil_front.compareMask);
|
||||
|
||||
@@ -15,12 +15,16 @@ struct ShaderVertexInputInfo;
|
||||
|
||||
struct PipelineDynamicParameters {
|
||||
bool stencil_test_enable = false;
|
||||
bool depth_bias_enable = false;
|
||||
|
||||
float viewport_scale[3] = {};
|
||||
float viewport_offset[3] = {};
|
||||
int scissor_ltrb[4] = {0};
|
||||
|
||||
float line_width = 1.0f;
|
||||
float depth_bias_constant_factor = 0.0f;
|
||||
float depth_bias_clamp = 0.0f;
|
||||
float depth_bias_slope_factor = 0.0f;
|
||||
uint32_t color_write_count = 1;
|
||||
bool color_write_enable[RENDER_COLOR_ATTACHMENTS_MAX] = {true, true};
|
||||
|
||||
@@ -33,10 +37,6 @@ struct PipelineDynamicParameters {
|
||||
static_assert(std::is_trivially_copyable_v<PipelineDynamicParameters>);
|
||||
static_assert(std::is_standard_layout_v<PipelineDynamicParameters>);
|
||||
static_assert(alignof(PipelineDynamicParameters) == 1);
|
||||
static_assert(sizeof(PipelineDynamicParameters) ==
|
||||
sizeof(bool) + sizeof(float[3]) + sizeof(float[3]) + sizeof(int[4]) + sizeof(float) +
|
||||
sizeof(uint32_t) + sizeof(bool[RENDER_COLOR_ATTACHMENTS_MAX]) +
|
||||
sizeof(PipelineStencilDynamicState) * 2);
|
||||
|
||||
[[nodiscard]] int32_t ResolveVertexOffset(uint32_t index_offset,
|
||||
const ShaderVertexInputInfo& vs_input_info);
|
||||
|
||||
@@ -260,6 +260,10 @@ static void VulkanFindPhysicalDevice(vk::Instance instance, vk::SurfaceKHR surfa
|
||||
LOGF("sampleRateShading is not supported\n");
|
||||
skip_device = true;
|
||||
}
|
||||
if (device_features2.features.depthBiasClamp != VK_TRUE) {
|
||||
LOGF("depthBiasClamp is not supported\n");
|
||||
skip_device = true;
|
||||
}
|
||||
|
||||
if (device_features2.features.fragmentStoresAndAtomics != VK_TRUE) {
|
||||
LOGF("fragmentStoresAndAtomics is not supported\n");
|
||||
@@ -549,6 +553,7 @@ static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, const V
|
||||
EXIT_NOT_IMPLEMENTED(required_features13.synchronization2 == VK_TRUE &&
|
||||
supported_features13.synchronization2 != VK_TRUE);
|
||||
EXIT_NOT_IMPLEMENTED(supported_features2.features.sampleRateShading != VK_TRUE);
|
||||
EXIT_NOT_IMPLEMENTED(supported_features2.features.depthBiasClamp != VK_TRUE);
|
||||
features12.timelineSemaphore = VK_TRUE;
|
||||
|
||||
vk::PhysicalDeviceFeatures device_features {};
|
||||
@@ -564,6 +569,7 @@ static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, const V
|
||||
device_features.independentBlend = VK_TRUE;
|
||||
device_features.tessellationShader = VK_TRUE;
|
||||
device_features.sampleRateShading = VK_TRUE;
|
||||
device_features.depthBiasClamp = VK_TRUE;
|
||||
graphics.sample_rate_shading_enabled = true;
|
||||
device_features.vertexPipelineStoresAndAtomics =
|
||||
supported_features2.features.vertexPipelineStoresAndAtomics;
|
||||
|
||||
Reference in New Issue
Block a user