mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
gpu: make cull mode and front face dynamic state
This commit is contained in:
@@ -125,6 +125,14 @@ void DynamicState::Commit(const GraphicContext& graphics, vk::CommandBuffer cmdb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (dirty_state.cull_mode) {
|
||||||
|
dirty_state.cull_mode = false;
|
||||||
|
cmdbuf.setCullMode(cull_mode);
|
||||||
|
}
|
||||||
|
if (dirty_state.front_face) {
|
||||||
|
dirty_state.front_face = false;
|
||||||
|
cmdbuf.setFrontFace(front_face);
|
||||||
|
}
|
||||||
if (dirty_state.blend_constants) {
|
if (dirty_state.blend_constants) {
|
||||||
dirty_state.blend_constants = false;
|
dirty_state.blend_constants = false;
|
||||||
cmdbuf.setBlendConstants(blend_constants.data());
|
cmdbuf.setBlendConstants(blend_constants.data());
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ struct DynamicState {
|
|||||||
bool stencil_back_write_mask : 1;
|
bool stencil_back_write_mask : 1;
|
||||||
bool stencil_back_compare_mask : 1;
|
bool stencil_back_compare_mask : 1;
|
||||||
|
|
||||||
|
bool cull_mode : 1;
|
||||||
|
bool front_face : 1;
|
||||||
|
|
||||||
bool blend_constants : 1;
|
bool blend_constants : 1;
|
||||||
bool color_write_enables : 1;
|
bool color_write_enables : 1;
|
||||||
bool line_width : 1;
|
bool line_width : 1;
|
||||||
@@ -86,6 +89,9 @@ struct DynamicState {
|
|||||||
uint32_t stencil_back_write_mask {};
|
uint32_t stencil_back_write_mask {};
|
||||||
uint32_t stencil_back_compare_mask {};
|
uint32_t stencil_back_compare_mask {};
|
||||||
|
|
||||||
|
vk::CullModeFlags cull_mode {};
|
||||||
|
vk::FrontFace front_face {};
|
||||||
|
|
||||||
std::array<float, 4> blend_constants {};
|
std::array<float, 4> blend_constants {};
|
||||||
std::array<vk::Bool32, RENDER_COLOR_ATTACHMENTS_MAX> color_write_enables {};
|
std::array<vk::Bool32, RENDER_COLOR_ATTACHMENTS_MAX> color_write_enables {};
|
||||||
uint32_t num_color_write_enables {};
|
uint32_t num_color_write_enables {};
|
||||||
@@ -221,6 +227,20 @@ struct DynamicState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetCullMode(const vk::CullModeFlags cull_mode_) {
|
||||||
|
if (cull_mode != cull_mode_) {
|
||||||
|
cull_mode = cull_mode_;
|
||||||
|
dirty_state.cull_mode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFrontFace(const vk::FrontFace front_face_) {
|
||||||
|
if (front_face != front_face_) {
|
||||||
|
front_face = front_face_;
|
||||||
|
dirty_state.front_face = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetBlendConstants(const std::array<float, 4> blend_constants_) {
|
void SetBlendConstants(const std::array<float, 4> blend_constants_) {
|
||||||
if (blend_constants != blend_constants_) {
|
if (blend_constants != blend_constants_) {
|
||||||
blend_constants = blend_constants_;
|
blend_constants = blend_constants_;
|
||||||
|
|||||||
@@ -1003,15 +1003,11 @@ PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline(const CommandBuffer&
|
|||||||
}
|
}
|
||||||
static_params.alpha_to_coverage_enable = ps_active && ctx.GetShaderRegisters().AlphaToMask();
|
static_params.alpha_to_coverage_enable = ps_active && ctx.GetShaderRegisters().AlphaToMask();
|
||||||
const bool rect_list = Prospero::IsRectList(command.GetUserConfig().GetPrimType());
|
const bool rect_list = Prospero::IsRectList(command.GetUserConfig().GetPrimType());
|
||||||
static_params.cull_back = !rect_list && mc.cull_back;
|
|
||||||
static_params.cull_front = !rect_list && mc.cull_front;
|
|
||||||
static_params.face = mc.face;
|
|
||||||
static_params.provoking_vtx_last = mc.provoking_vtx_last;
|
static_params.provoking_vtx_last = mc.provoking_vtx_last;
|
||||||
static_params.polygon_mode =
|
static_params.polygon_mode =
|
||||||
ResolvePolygonMode(mc, static_params.cull_front, static_params.cull_back);
|
ResolvePolygonMode(mc, !rect_list && mc.cull_front, !rect_list && mc.cull_back);
|
||||||
if (tessellation) {
|
if (tessellation) {
|
||||||
static_params.patch_control_points =
|
static_params.patch_control_points = vs_input_info.tess.input_control_points;
|
||||||
static_cast<uint8_t>(vs_input_info.tess.input_control_points);
|
|
||||||
} else if (!mesh && static_params.topology == vk::PrimitiveTopology::ePatchList) {
|
} else if (!mesh && static_params.topology == vk::PrimitiveTopology::ePatchList) {
|
||||||
// Rectangle lists expand through generated tessellation stages.
|
// Rectangle lists expand through generated tessellation stages.
|
||||||
static_params.patch_control_points = 3;
|
static_params.patch_control_points = 3;
|
||||||
|
|||||||
@@ -54,15 +54,12 @@ struct PipelineStaticParameters {
|
|||||||
bool depth_clip_enable = true;
|
bool depth_clip_enable = true;
|
||||||
vk::PrimitiveTopology topology = vk::PrimitiveTopology::ePointList;
|
vk::PrimitiveTopology topology = vk::PrimitiveTopology::ePointList;
|
||||||
// 0 without tessellation, 3 for a rectangle list, else the input control points.
|
// 0 without tessellation, 3 for a rectangle list, else the input control points.
|
||||||
uint8_t patch_control_points = 0;
|
uint32_t patch_control_points = 0;
|
||||||
bool primitive_restart_enable = false;
|
bool primitive_restart_enable = false;
|
||||||
uint32_t samples = 1;
|
uint32_t samples = 1;
|
||||||
bool sample_shading_enable = false;
|
bool sample_shading_enable = false;
|
||||||
bool alpha_to_coverage_enable = false;
|
bool alpha_to_coverage_enable = false;
|
||||||
uint32_t color_mask[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
uint32_t color_mask[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
||||||
bool cull_front = false;
|
|
||||||
bool cull_back = false;
|
|
||||||
bool face = false;
|
|
||||||
bool provoking_vtx_last = false;
|
bool provoking_vtx_last = false;
|
||||||
vk::PolygonMode polygon_mode = vk::PolygonMode::eFill;
|
vk::PolygonMode polygon_mode = vk::PolygonMode::eFill;
|
||||||
uint8_t color_srcblend[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
uint8_t color_srcblend[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
||||||
|
|||||||
@@ -219,17 +219,6 @@ void CreatePipelineInternal(GraphicContext& graphics, PipelineCache::Pipeline& p
|
|||||||
vk::PipelineViewportStateCreateInfo viewport_state {};
|
vk::PipelineViewportStateCreateInfo viewport_state {};
|
||||||
viewport_state.pNext = &depth_clip_control;
|
viewport_state.pNext = &depth_clip_control;
|
||||||
|
|
||||||
vk::CullModeFlags cull_mode = vk::CullModeFlagBits::eNone;
|
|
||||||
if (static_params.cull_back) {
|
|
||||||
cull_mode |= vk::CullModeFlagBits::eBack;
|
|
||||||
}
|
|
||||||
if (static_params.cull_front) {
|
|
||||||
cull_mode |= vk::CullModeFlagBits::eFront;
|
|
||||||
}
|
|
||||||
|
|
||||||
vk::FrontFace front_face =
|
|
||||||
(static_params.face ? vk::FrontFace::eClockwise : vk::FrontFace::eCounterClockwise);
|
|
||||||
|
|
||||||
vk::PipelineRasterizationDepthClipStateCreateInfoEXT clip_ext {};
|
vk::PipelineRasterizationDepthClipStateCreateInfoEXT clip_ext {};
|
||||||
clip_ext.depthClipEnable = static_params.depth_clip_enable ? VK_TRUE : VK_FALSE;
|
clip_ext.depthClipEnable = static_params.depth_clip_enable ? VK_TRUE : VK_FALSE;
|
||||||
|
|
||||||
@@ -250,8 +239,6 @@ void CreatePipelineInternal(GraphicContext& graphics, PipelineCache::Pipeline& p
|
|||||||
provoking_vertex.pNext = rasterizer.pNext;
|
provoking_vertex.pNext = rasterizer.pNext;
|
||||||
rasterizer.pNext = &provoking_vertex;
|
rasterizer.pNext = &provoking_vertex;
|
||||||
}
|
}
|
||||||
rasterizer.cullMode = cull_mode;
|
|
||||||
rasterizer.frontFace = front_face;
|
|
||||||
rasterizer.polygonMode = static_params.polygon_mode;
|
rasterizer.polygonMode = static_params.polygon_mode;
|
||||||
rasterizer.lineWidth = 1.0f;
|
rasterizer.lineWidth = 1.0f;
|
||||||
|
|
||||||
@@ -347,6 +334,8 @@ void CreatePipelineInternal(GraphicContext& graphics, PipelineCache::Pipeline& p
|
|||||||
vk::DynamicState::eViewportWithCount,
|
vk::DynamicState::eViewportWithCount,
|
||||||
vk::DynamicState::eScissorWithCount,
|
vk::DynamicState::eScissorWithCount,
|
||||||
vk::DynamicState::eLineWidth,
|
vk::DynamicState::eLineWidth,
|
||||||
|
vk::DynamicState::eCullMode,
|
||||||
|
vk::DynamicState::eFrontFace,
|
||||||
vk::DynamicState::eDepthTestEnable,
|
vk::DynamicState::eDepthTestEnable,
|
||||||
vk::DynamicState::eDepthWriteEnable,
|
vk::DynamicState::eDepthWriteEnable,
|
||||||
vk::DynamicState::eDepthCompareOp,
|
vk::DynamicState::eDepthCompareOp,
|
||||||
|
|||||||
@@ -403,6 +403,20 @@ static void UpdateGraphicsDynamicState(const CommandBuffer& buffer, DynamicState
|
|||||||
dynamic_state.SetDepthBias(constant_factor, poly_offset.clamp, slope_factor);
|
dynamic_state.SetDepthBias(constant_factor, poly_offset.clamp, slope_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rect lists are drawn without culling.
|
||||||
|
vk::CullModeFlags cull_mode {};
|
||||||
|
if (!Prospero::IsRectList(buffer.GetUserConfig().GetPrimType())) {
|
||||||
|
if (mode.cull_front) {
|
||||||
|
cull_mode |= vk::CullModeFlagBits::eFront;
|
||||||
|
}
|
||||||
|
if (mode.cull_back) {
|
||||||
|
cull_mode |= vk::CullModeFlagBits::eBack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dynamic_state.SetCullMode(cull_mode);
|
||||||
|
dynamic_state.SetFrontFace(mode.face ? vk::FrontFace::eClockwise
|
||||||
|
: vk::FrontFace::eCounterClockwise);
|
||||||
|
|
||||||
dynamic_state.SetStencilTestEnabled(depth.stencil_test_enable);
|
dynamic_state.SetStencilTestEnabled(depth.stencil_test_enable);
|
||||||
if (depth.stencil_test_enable) {
|
if (depth.stencil_test_enable) {
|
||||||
const auto& front = depth.stencil_front;
|
const auto& front = depth.stencil_front;
|
||||||
|
|||||||
@@ -18826,6 +18826,10 @@ public:
|
|||||||
cmd.setViewportWithCount(1, &viewport);
|
cmd.setViewportWithCount(1, &viewport);
|
||||||
cmd.setScissorWithCount(1, &scissor);
|
cmd.setScissorWithCount(1, &scissor);
|
||||||
cmd.setLineWidth(1);
|
cmd.setLineWidth(1);
|
||||||
|
cmd.setCullMode(vk::CullModeFlagBits::eNone);
|
||||||
|
cmd.setFrontFace(registers.GetModeControl().face
|
||||||
|
? vk::FrontFace::eClockwise
|
||||||
|
: vk::FrontFace::eCounterClockwise);
|
||||||
cmd.setDepthTestEnable(depth.depth_test_enable);
|
cmd.setDepthTestEnable(depth.depth_test_enable);
|
||||||
cmd.setDepthWriteEnable(depth.depth_write_enable);
|
cmd.setDepthWriteEnable(depth.depth_write_enable);
|
||||||
cmd.setDepthCompareOp(depth.depth_compare_op);
|
cmd.setDepthCompareOp(depth.depth_compare_op);
|
||||||
@@ -19023,6 +19027,9 @@ public:
|
|||||||
const std::array stencil_pipelines{
|
const std::array stencil_pipelines{
|
||||||
pipeline(true, 2, 2, false, true).pipeline,
|
pipeline(true, 2, 2, false, true).pipeline,
|
||||||
pipeline(true, 2, 2, false, false).pipeline};
|
pipeline(true, 2, 2, false, false).pipeline};
|
||||||
|
Require(name, "dynamic winding pipeline reuse",
|
||||||
|
stencil_pipelines[0] == stencil_pipelines[1],
|
||||||
|
"the winding changed the graphics pipeline");
|
||||||
const auto check_stencil = [&](const char *label, bool back_face,
|
const auto check_stencil = [&](const char *label, bool back_face,
|
||||||
uint8_t initial, uint8_t written) {
|
uint8_t initial, uint8_t written) {
|
||||||
vk::ClearValue clear{};
|
vk::ClearValue clear{};
|
||||||
@@ -19655,6 +19662,22 @@ public:
|
|||||||
"native vertex or instance offset was applied twice");
|
"native vertex or instance offset was applied twice");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// With back faces culled, the triangle draws for exactly one winding.
|
||||||
|
const auto draws_with_back_cull = [&](bool clockwise) {
|
||||||
|
registers.SetModeControl({.cull_back = true, .face = clockwise});
|
||||||
|
TextureCacheTestAccess::ClearImage(cache, scheduler.Current(), sparse_color.image_id,
|
||||||
|
{vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}, {});
|
||||||
|
RenderExecutorTestAccess::DrawAuto(executor, scheduler.Current(),
|
||||||
|
{.vertex_count = 3, .instance_count = 1, .first_vertex = 7, .first_instance = 5,
|
||||||
|
.offset_source = DrawOffsetSource::IndirectArgs});
|
||||||
|
const auto pixels = ReadCachedTexel(name, context, sparse_color.image_id,
|
||||||
|
{}, {extent, extent, 1});
|
||||||
|
return std::ranges::any_of(pixels, [](u32 word) { return word != 0; });
|
||||||
|
};
|
||||||
|
Require("DynamicCullMode", "back faces culled by winding",
|
||||||
|
draws_with_back_cull(false) != draws_with_back_cull(true),
|
||||||
|
"the draw's cull mode or front face did not reach the host GPU");
|
||||||
|
registers.SetModeControl({});
|
||||||
|
|
||||||
// Indirect records come from the GPU copy; the CPU backing holds zeros. In each pair the
|
// Indirect records come from the GPU copy; the CPU backing holds zeros. In each pair the
|
||||||
// first record draws nothing and the second covers the target, through vertex offset 7
|
// first record draws nothing and the second covers the target, through vertex offset 7
|
||||||
@@ -19800,9 +19823,10 @@ public:
|
|||||||
registers.SetPsInputEna(2);
|
registers.SetPsInputEna(2);
|
||||||
registers.SetPsInputAddr(2);
|
registers.SetPsInputAddr(2);
|
||||||
registers.SetPsInputSettings(0, 0);
|
registers.SetPsInputSettings(0, 0);
|
||||||
|
// Rect lists are drawn without culling.
|
||||||
const auto check_rect = [&](Prospero::PrimitiveType primitive, const char *rect_name) {
|
const auto check_rect = [&](Prospero::PrimitiveType primitive, const char *rect_name) {
|
||||||
user_config.SetPrimitiveType(primitive);
|
user_config.SetPrimitiveType(primitive);
|
||||||
registers.SetModeControl({});
|
registers.SetModeControl({.cull_front = true, .cull_back = true});
|
||||||
TextureCacheTestAccess::ClearImage(cache, scheduler.Current(), sparse_color.image_id,
|
TextureCacheTestAccess::ClearImage(cache, scheduler.Current(), sparse_color.image_id,
|
||||||
{vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}, {});
|
{vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}, {});
|
||||||
RenderExecutorTestAccess::DrawAuto(
|
RenderExecutorTestAccess::DrawAuto(
|
||||||
|
|||||||
Reference in New Issue
Block a user