mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
graphics: fix last provoking vertex on PS5
This commit is contained in:
@@ -31,6 +31,7 @@ struct GraphicContext {
|
|||||||
bool compute_subgroup_size_control_enabled = false;
|
bool compute_subgroup_size_control_enabled = false;
|
||||||
bool sample_rate_shading_enabled = false;
|
bool sample_rate_shading_enabled = false;
|
||||||
bool attachment_feedback_loop_enabled = false;
|
bool attachment_feedback_loop_enabled = false;
|
||||||
|
bool provoking_vertex_last_enabled = false;
|
||||||
bool supports_block_texel_view = false;
|
bool supports_block_texel_view = false;
|
||||||
bool mesh_shader_enabled = false;
|
bool mesh_shader_enabled = false;
|
||||||
vk::PhysicalDeviceMeshShaderPropertiesEXT mesh_shader_properties = {};
|
vk::PhysicalDeviceMeshShaderPropertiesEXT mesh_shader_properties = {};
|
||||||
|
|||||||
@@ -478,7 +478,6 @@ static void McCheck(const HW::ModeControl& c) {
|
|||||||
logged = true;
|
logged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXIT_NOT_IMPLEMENTED(c.provoking_vtx_last != false);
|
|
||||||
EXIT_NOT_IMPLEMENTED(c.persp_corr_dis != false);
|
EXIT_NOT_IMPLEMENTED(c.persp_corr_dis != false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -728,6 +728,7 @@ PipelineCache::Pipeline& PipelineCache::CreateGraphicsPipeline(
|
|||||||
static_params.cull_back = !rect_list && mc.cull_back;
|
static_params.cull_back = !rect_list && mc.cull_back;
|
||||||
static_params.cull_front = !rect_list && mc.cull_front;
|
static_params.cull_front = !rect_list && mc.cull_front;
|
||||||
static_params.face = mc.face;
|
static_params.face = mc.face;
|
||||||
|
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, static_params.cull_front, static_params.cull_back);
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ struct PipelineStaticParameters {
|
|||||||
bool cull_front = false;
|
bool cull_front = false;
|
||||||
bool cull_back = false;
|
bool cull_back = false;
|
||||||
bool face = false;
|
bool face = 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] = {};
|
||||||
uint8_t color_comb_fcn[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
uint8_t color_comb_fcn[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
||||||
@@ -68,7 +69,7 @@ struct PipelineStaticParameters {
|
|||||||
static_assert(std::is_trivially_copyable_v<PipelineStaticParameters>);
|
static_assert(std::is_trivially_copyable_v<PipelineStaticParameters>);
|
||||||
static_assert(std::is_standard_layout_v<PipelineStaticParameters>);
|
static_assert(std::is_standard_layout_v<PipelineStaticParameters>);
|
||||||
static_assert(alignof(PipelineStaticParameters) == 1);
|
static_assert(alignof(PipelineStaticParameters) == 1);
|
||||||
static_assert(sizeof(PipelineStaticParameters) == 165);
|
static_assert(sizeof(PipelineStaticParameters) == 166);
|
||||||
|
|
||||||
struct PipelineRenderingState {
|
struct PipelineRenderingState {
|
||||||
std::array<vk::Format, RENDER_COLOR_ATTACHMENTS_MAX> color_formats {};
|
std::array<vk::Format, RENDER_COLOR_ATTACHMENTS_MAX> color_formats {};
|
||||||
|
|||||||
@@ -595,6 +595,15 @@ void CreatePipelineInternal(
|
|||||||
#if !defined(__APPLE__)
|
#if !defined(__APPLE__)
|
||||||
rasterizer.pNext = &clip_ext;
|
rasterizer.pNext = &clip_ext;
|
||||||
#endif
|
#endif
|
||||||
|
vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT provoking_vertex {};
|
||||||
|
EXIT_NOT_IMPLEMENTED(static_params.provoking_vtx_last &&
|
||||||
|
!graphics.provoking_vertex_last_enabled);
|
||||||
|
if (graphics.provoking_vertex_last_enabled) {
|
||||||
|
provoking_vertex.provokingVertexMode = static_params.provoking_vtx_last
|
||||||
|
? vk::ProvokingVertexModeEXT::eLastVertex : vk::ProvokingVertexModeEXT::eFirstVertex;
|
||||||
|
provoking_vertex.pNext = rasterizer.pNext;
|
||||||
|
rasterizer.pNext = &provoking_vertex;
|
||||||
|
}
|
||||||
rasterizer.cullMode = cull_mode;
|
rasterizer.cullMode = cull_mode;
|
||||||
rasterizer.frontFace = front_face;
|
rasterizer.frontFace = front_face;
|
||||||
rasterizer.polygonMode = static_params.polygon_mode;
|
rasterizer.polygonMode = static_params.polygon_mode;
|
||||||
|
|||||||
@@ -637,7 +637,15 @@ static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, const V
|
|||||||
feedback_layout.pNext = &feedback_dynamic;
|
feedback_layout.pNext = &feedback_dynamic;
|
||||||
supported_features2.pNext = &feedback_layout;
|
supported_features2.pNext = &feedback_layout;
|
||||||
}
|
}
|
||||||
|
const bool provoking_extension =
|
||||||
|
HasExtension(device_extensions, VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
|
||||||
|
vk::PhysicalDeviceProvokingVertexFeaturesEXT provoking_vertex {};
|
||||||
|
if (provoking_extension) {
|
||||||
|
provoking_vertex.pNext = supported_features2.pNext;
|
||||||
|
supported_features2.pNext = &provoking_vertex;
|
||||||
|
}
|
||||||
physical_device.getFeatures2(&supported_features2);
|
physical_device.getFeatures2(&supported_features2);
|
||||||
|
graphics.provoking_vertex_last_enabled = provoking_extension && provoking_vertex.provokingVertexLast;
|
||||||
graphics.attachment_feedback_loop_enabled =
|
graphics.attachment_feedback_loop_enabled =
|
||||||
feedback_extensions && feedback_layout.attachmentFeedbackLoopLayout &&
|
feedback_extensions && feedback_layout.attachmentFeedbackLoopLayout &&
|
||||||
feedback_dynamic.attachmentFeedbackLoopDynamicState;
|
feedback_dynamic.attachmentFeedbackLoopDynamicState;
|
||||||
@@ -753,6 +761,11 @@ static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, const V
|
|||||||
create_info.pNext = graphics.attachment_feedback_loop_enabled
|
create_info.pNext = graphics.attachment_feedback_loop_enabled
|
||||||
? static_cast<void*>(&feedback_layout)
|
? static_cast<void*>(&feedback_layout)
|
||||||
: feedback_dynamic.pNext;
|
: feedback_dynamic.pNext;
|
||||||
|
if (graphics.provoking_vertex_last_enabled) {
|
||||||
|
provoking_vertex.pNext = const_cast<void*>(create_info.pNext);
|
||||||
|
provoking_vertex.transformFeedbackPreservesProvokingVertex = VK_FALSE;
|
||||||
|
create_info.pNext = &provoking_vertex;
|
||||||
|
}
|
||||||
create_info.flags = {};
|
create_info.flags = {};
|
||||||
create_info.pQueueCreateInfos = &queue_create_info;
|
create_info.pQueueCreateInfos = &queue_create_info;
|
||||||
create_info.queueCreateInfoCount = 1;
|
create_info.queueCreateInfoCount = 1;
|
||||||
@@ -1145,6 +1158,7 @@ void WindowContext::CreateVulkan() {
|
|||||||
graphic_ctx.memory_budget_ext_enabled = true;
|
graphic_ctx.memory_budget_ext_enabled = true;
|
||||||
}
|
}
|
||||||
for (const auto* extension: {VK_EXT_ROBUSTNESS_2_EXTENSION_NAME,
|
for (const auto* extension: {VK_EXT_ROBUSTNESS_2_EXTENSION_NAME,
|
||||||
|
VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME,
|
||||||
VK_EXT_MESH_SHADER_EXTENSION_NAME,
|
VK_EXT_MESH_SHADER_EXTENSION_NAME,
|
||||||
VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME}) {
|
VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME}) {
|
||||||
if (HasExtension(available_extensions, extension)) {
|
if (HasExtension(available_extensions, extension)) {
|
||||||
|
|||||||
@@ -11534,7 +11534,8 @@ public:
|
|||||||
test.fragment_code.push_back(EncodeExp0(0x08, 0x1, false));
|
test.fragment_code.push_back(EncodeExp0(0x08, 0x1, false));
|
||||||
test.fragment_code.push_back(EncodeExp1(1, 1, 1, 1));
|
test.fragment_code.push_back(EncodeExp1(1, 1, 1, 1));
|
||||||
} else {
|
} else {
|
||||||
AppendVMovLiteral(&test.fragment_code, 0, 0x3f800000u);
|
test.pixel_interpolator_settings = {0x400u};
|
||||||
|
test.fragment_code.push_back(EncodeVintrp(0x02, 0, 0, 0, 2));
|
||||||
}
|
}
|
||||||
test.fragment_code.push_back(EncodeExp0(0x00, 0xf));
|
test.fragment_code.push_back(EncodeExp0(0x00, 0xf));
|
||||||
test.fragment_code.push_back(EncodeExp1(0, 0, 0, 0));
|
test.fragment_code.push_back(EncodeExp1(0, 0, 0, 0));
|
||||||
@@ -11583,8 +11584,8 @@ public:
|
|||||||
color.desc.view_info.usage = vk::ImageUsageFlagBits::eColorAttachment;
|
color.desc.view_info.usage = vk::ImageUsageFlagBits::eColorAttachment;
|
||||||
color.image_id = cache.FindImage(color.desc);
|
color.image_id = cache.FindImage(color.desc);
|
||||||
std::array<float, 18> vertices{
|
std::array<float, 18> vertices{
|
||||||
-0.75f, -0.75f, 1, 1, 1, 1, 0.75f, -0.75f, 1, 1, 1, 1,
|
-0.75f, -0.75f, 1, 1, 1, 1, 0.75f, -0.75f, 0.5f, 1, 1, 1,
|
||||||
0.0f, 0.75f, 1, 1, 1, 1};
|
0.0f, 0.75f, 0.25f, 1, 1, 1};
|
||||||
if (depth_feedback) {
|
if (depth_feedback) {
|
||||||
vertices = {-1, -1, 0, 0, 0, 1, 3, -1, 2, 0, 0, 1, -1, 3, 0, 2, 0, 1};
|
vertices = {-1, -1, 0, 0, 0, 1, 3, -1, 2, 0, 0, 1, -1, 3, 0, 2, 0, 1};
|
||||||
}
|
}
|
||||||
@@ -11592,11 +11593,13 @@ public:
|
|||||||
std::memcpy(vertex_words.data(), vertices.data(), sizeof(vertices));
|
std::memcpy(vertex_words.data(), vertices.data(), sizeof(vertices));
|
||||||
auto buffer = CreateHostBuffer(name, sizeof(vertices), vk::BufferUsageFlagBits::eVertexBuffer,
|
auto buffer = CreateHostBuffer(name, sizeof(vertices), vk::BufferUsageFlagBits::eVertexBuffer,
|
||||||
vertex_words);
|
vertex_words);
|
||||||
const auto pipeline = [&](bool enabled, uint8_t front, uint8_t back) -> PipelineCache::Pipeline & {
|
const auto pipeline = [&](bool enabled, uint8_t front, uint8_t back,
|
||||||
|
bool provoking_last = false) -> PipelineCache::Pipeline & {
|
||||||
HW::ModeControl mode{};
|
HW::ModeControl mode{};
|
||||||
mode.poly_mode = enabled;
|
mode.poly_mode = enabled;
|
||||||
mode.polymode_front_ptype = front;
|
mode.polymode_front_ptype = front;
|
||||||
mode.polymode_back_ptype = back;
|
mode.polymode_back_ptype = back;
|
||||||
|
mode.provoking_vtx_last = provoking_last;
|
||||||
registers.SetModeControl(mode);
|
registers.SetModeControl(mode);
|
||||||
return context.GetPipelineCache().CreateGraphicsPipeline(
|
return context.GetPipelineCache().CreateGraphicsPipeline(
|
||||||
std::span{&color, 1u}, depth, vertex, scheduler.Current(), &pixel,
|
std::span{&color, 1u}, depth, vertex, scheduler.Current(), &pixel,
|
||||||
@@ -11686,6 +11689,19 @@ public:
|
|||||||
line_pixels[interior] == 0 &&
|
line_pixels[interior] == 0 &&
|
||||||
std::ranges::any_of(line_pixels, [](u32 value) { return value == 0x3f800000u; }),
|
std::ranges::any_of(line_pixels, [](u32 value) { return value == 0x3f800000u; }),
|
||||||
"wireframe did not preserve triangle edges while leaving its interior empty");
|
"wireframe did not preserve triangle edges while leaving its interior empty");
|
||||||
|
auto &last_vertex = pipeline(true, 2, 2, true);
|
||||||
|
Require(name, "provoking vertex pipeline cache",
|
||||||
|
last_vertex.pipeline != filled.pipeline &&
|
||||||
|
pipeline(true, 2, 2, true).pipeline == last_vertex.pipeline &&
|
||||||
|
pipeline(true, 2, 2).pipeline == filled.pipeline,
|
||||||
|
"first and last provoking vertices did not keep distinct cached pipelines");
|
||||||
|
draw(last_vertex);
|
||||||
|
const auto last_pixels = read_color();
|
||||||
|
for (size_t i = 0; i < solid_pixels.size(); i++) {
|
||||||
|
Require(name, "flat provoking vertex output",
|
||||||
|
last_pixels[i] == (solid_pixels[i] == 0 ? 0 : 0x3e800000u),
|
||||||
|
"last-vertex flat shading changed coverage or did not use vertex two");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
resources.UnmapMemory(depth_address, allocation_size);
|
resources.UnmapMemory(depth_address, allocation_size);
|
||||||
scheduler.Finish();
|
scheduler.Finish();
|
||||||
@@ -12997,6 +13013,7 @@ private:
|
|||||||
m_runtime_context.queue_family = m_queue_family;
|
m_runtime_context.queue_family = m_queue_family;
|
||||||
m_runtime_context.queue = m_queue;
|
m_runtime_context.queue = m_queue;
|
||||||
m_runtime_context.attachment_feedback_loop_enabled = true;
|
m_runtime_context.attachment_feedback_loop_enabled = true;
|
||||||
|
m_runtime_context.provoking_vertex_last_enabled = true;
|
||||||
|
|
||||||
VmaVulkanFunctions functions{};
|
VmaVulkanFunctions functions{};
|
||||||
functions.vkGetInstanceProcAddr =
|
functions.vkGetInstanceProcAddr =
|
||||||
@@ -13109,9 +13126,11 @@ private:
|
|||||||
available_feedback_layout.pNext = &available_color_write;
|
available_feedback_layout.pNext = &available_color_write;
|
||||||
vk::PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT available_feedback_dynamic{};
|
vk::PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT available_feedback_dynamic{};
|
||||||
available_feedback_dynamic.pNext = &available_feedback_layout;
|
available_feedback_dynamic.pNext = &available_feedback_layout;
|
||||||
|
vk::PhysicalDeviceProvokingVertexFeaturesEXT available_provoking_vertex{};
|
||||||
|
available_provoking_vertex.pNext = &available_feedback_dynamic;
|
||||||
vk::PhysicalDeviceFeatures2 available_features2{};
|
vk::PhysicalDeviceFeatures2 available_features2{};
|
||||||
available_features2.sType = vk::StructureType::ePhysicalDeviceFeatures2;
|
available_features2.sType = vk::StructureType::ePhysicalDeviceFeatures2;
|
||||||
available_features2.pNext = &available_feedback_dynamic;
|
available_features2.pNext = &available_provoking_vertex;
|
||||||
m_physical_device.getFeatures2(&available_features2);
|
m_physical_device.getFeatures2(&available_features2);
|
||||||
Require("VulkanHarness", "dispatch",
|
Require("VulkanHarness", "dispatch",
|
||||||
available_features.shaderStorageImageWriteWithoutFormat == true,
|
available_features.shaderStorageImageWriteWithoutFormat == true,
|
||||||
@@ -13143,7 +13162,8 @@ private:
|
|||||||
available_depth_clip.depthClipEnable && available_clip_control.depthClipControl &&
|
available_depth_clip.depthClipEnable && available_clip_control.depthClipControl &&
|
||||||
available_color_write.colorWriteEnable &&
|
available_color_write.colorWriteEnable &&
|
||||||
available_feedback_layout.attachmentFeedbackLoopLayout &&
|
available_feedback_layout.attachmentFeedbackLoopLayout &&
|
||||||
available_feedback_dynamic.attachmentFeedbackLoopDynamicState,
|
available_feedback_dynamic.attachmentFeedbackLoopDynamicState &&
|
||||||
|
available_provoking_vertex.provokingVertexLast,
|
||||||
"production rasterization features are not supported");
|
"production rasterization features are not supported");
|
||||||
|
|
||||||
float priority = 1.0f;
|
float priority = 1.0f;
|
||||||
@@ -13191,7 +13211,10 @@ private:
|
|||||||
vk::PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT feedback_dynamic{};
|
vk::PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT feedback_dynamic{};
|
||||||
feedback_dynamic.pNext = &feedback_layout;
|
feedback_dynamic.pNext = &feedback_layout;
|
||||||
feedback_dynamic.attachmentFeedbackLoopDynamicState = true;
|
feedback_dynamic.attachmentFeedbackLoopDynamicState = true;
|
||||||
device_info.pNext = &feedback_dynamic;
|
vk::PhysicalDeviceProvokingVertexFeaturesEXT provoking_vertex{};
|
||||||
|
provoking_vertex.pNext = &feedback_dynamic;
|
||||||
|
provoking_vertex.provokingVertexLast = available_provoking_vertex.provokingVertexLast;
|
||||||
|
device_info.pNext = &provoking_vertex;
|
||||||
vk::PhysicalDeviceFeatures device_features{};
|
vk::PhysicalDeviceFeatures device_features{};
|
||||||
device_features.shaderStorageImageWriteWithoutFormat = true;
|
device_features.shaderStorageImageWriteWithoutFormat = true;
|
||||||
device_features.shaderImageGatherExtended = true;
|
device_features.shaderImageGatherExtended = true;
|
||||||
@@ -13207,7 +13230,8 @@ private:
|
|||||||
VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME,
|
VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME,
|
||||||
VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME,
|
VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME,
|
||||||
VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME,
|
VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME,
|
||||||
VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME};
|
VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME,
|
||||||
|
VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME};
|
||||||
device_info.enabledExtensionCount = std::size(device_extensions);
|
device_info.enabledExtensionCount = std::size(device_extensions);
|
||||||
device_info.ppEnabledExtensionNames = device_extensions;
|
device_info.ppEnabledExtensionNames = device_extensions;
|
||||||
RequireVk("VulkanHarness", "dispatch",
|
RequireVk("VulkanHarness", "dispatch",
|
||||||
|
|||||||
Reference in New Issue
Block a user