shader compiler: Ensure all clip distances are initialized when used
Thank you to Ryujinx (riperiperi specifically) for the pointer towards clip distances Huge thanks to crueter for finding where the code works and Camille for giving pointers along the way.
This commit is contained in:
parent
4596295b51
commit
e4843fc615
4 changed files with 46 additions and 18 deletions
|
@ -53,6 +53,15 @@ std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) {
|
||||||
return OutputAccessChain(ctx, ctx.output_f32, info.id, index_id);
|
return OutputAccessChain(ctx, ctx.output_f32, info.id, index_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < ctx.profile.max_user_clip_distances; ++i) {
|
||||||
|
if (!clip_distance_written.test(i)) {
|
||||||
|
const Id idx = ctx.Const(i);
|
||||||
|
const Id element = OutputAccessChain(ctx, ctx.output_f32, ctx.clip_distances, idx);
|
||||||
|
ctx.OpStore(element, ctx.Const(0.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (attr) {
|
switch (attr) {
|
||||||
case IR::Attribute::PointSize:
|
case IR::Attribute::PointSize:
|
||||||
return ctx.output_point_size;
|
return ctx.output_point_size;
|
||||||
|
@ -421,6 +430,14 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, [[maybe_un
|
||||||
if (Sirit::ValidId(output->type)) {
|
if (Sirit::ValidId(output->type)) {
|
||||||
value = ctx.OpBitcast(output->type, value);
|
value = ctx.OpBitcast(output->type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr IR::Attribute cd0 = IR::Attribute::ClipDistance0;
|
||||||
|
static constexpr IR::Attribute cd7 = IR::Attribute::ClipDistance7;
|
||||||
|
|
||||||
|
if (attr >= cd0 && attr <= cd7) {
|
||||||
|
const u32 idx = (u32) attr - (u32) cd0;
|
||||||
|
clip_distance_written.set(idx);
|
||||||
|
}
|
||||||
ctx.OpStore(output->pointer, value);
|
ctx.OpStore(output->pointer, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ void EmitPrologue(EmitContext& ctx) {
|
||||||
ctx.OpStore(element_info.id, value);
|
ctx.OpStore(element_info.id, value);
|
||||||
element += num;
|
element += num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ctx.stage == Stage::VertexB || ctx.stage == Stage::Geometry) {
|
if (ctx.stage == Stage::VertexB || ctx.stage == Stage::Geometry) {
|
||||||
SetFixedPipelinePointSize(ctx);
|
SetFixedPipelinePointSize(ctx);
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
namespace Shader::Backend::SPIRV {
|
namespace Shader::Backend::SPIRV {
|
||||||
|
|
||||||
|
std::bitset<8> clip_distance_written;
|
||||||
|
|
||||||
using Sirit::Id;
|
using Sirit::Id;
|
||||||
|
|
||||||
class VectorTypes {
|
class VectorTypes {
|
||||||
|
|
|
@ -260,7 +260,7 @@ GraphicsPipeline::GraphicsPipeline(
|
||||||
num_textures += Shader::NumDescriptors(info->texture_descriptors);
|
num_textures += Shader::NumDescriptors(info->texture_descriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track compilation start time for performance metrics
|
// Track compilation start time for performance metrics
|
||||||
const auto start_time = std::chrono::high_resolution_clock::now();
|
const auto start_time = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
auto func{[this, shader_notify, &render_pass_cache, &descriptor_pool, pipeline_statistics, start_time] {
|
auto func{[this, shader_notify, &render_pass_cache, &descriptor_pool, pipeline_statistics, start_time] {
|
||||||
|
@ -284,12 +284,12 @@ GraphicsPipeline::GraphicsPipeline(
|
||||||
Validate();
|
Validate();
|
||||||
MakePipeline(render_pass);
|
MakePipeline(render_pass);
|
||||||
|
|
||||||
// Performance measurement
|
// Performance measurement
|
||||||
const auto end_time = std::chrono::high_resolution_clock::now();
|
const auto end_time = std::chrono::high_resolution_clock::now();
|
||||||
const auto compilation_time = std::chrono::duration_cast<std::chrono::milliseconds>(
|
const auto compilation_time = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
end_time - start_time).count();
|
end_time - start_time).count();
|
||||||
|
|
||||||
// Log shader compilation time for slow shaders to help diagnose performance issues
|
// Log shader compilation time for slow shaders to help diagnose performance issues
|
||||||
if (compilation_time > 100) { // Only log very slow compilations
|
if (compilation_time > 100) { // Only log very slow compilations
|
||||||
LOG_DEBUG(Render_Vulkan, "Compiled graphics pipeline in {}ms", compilation_time);
|
LOG_DEBUG(Render_Vulkan, "Compiled graphics pipeline in {}ms", compilation_time);
|
||||||
}
|
}
|
||||||
|
@ -375,7 +375,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
||||||
views[view_index++] = {
|
views[view_index++] = {
|
||||||
.index = handle.first,
|
.index = handle.first,
|
||||||
.blacklist = blacklist,
|
.blacklist = blacklist,
|
||||||
.id = {},
|
.id = {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
@ -650,14 +650,14 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.topology = input_assembly_topology,
|
.topology = input_assembly_topology,
|
||||||
.primitiveRestartEnable =
|
.primitiveRestartEnable =
|
||||||
dynamic.primitive_restart_enable != 0 &&
|
dynamic.primitive_restart_enable != 0 &&
|
||||||
((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
|
((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
|
||||||
device.IsTopologyListPrimitiveRestartSupported()) ||
|
device.IsTopologyListPrimitiveRestartSupported()) ||
|
||||||
SupportsPrimitiveRestart(input_assembly_topology) ||
|
SupportsPrimitiveRestart(input_assembly_topology) ||
|
||||||
(input_assembly_topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
|
(input_assembly_topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
|
||||||
device.IsPatchListPrimitiveRestartSupported()))
|
device.IsPatchListPrimitiveRestartSupported()))
|
||||||
? VK_TRUE
|
? VK_TRUE
|
||||||
: VK_FALSE,
|
: VK_FALSE,
|
||||||
};
|
};
|
||||||
const VkPipelineTessellationStateCreateInfo tessellation_ci{
|
const VkPipelineTessellationStateCreateInfo tessellation_ci{
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
|
||||||
|
@ -700,11 +700,11 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.depthClampEnable =
|
.depthClampEnable =
|
||||||
static_cast<VkBool32>(dynamic.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE),
|
static_cast<VkBool32>(dynamic.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE),
|
||||||
.rasterizerDiscardEnable =
|
.rasterizerDiscardEnable =
|
||||||
static_cast<VkBool32>(dynamic.rasterize_enable == 0 ? VK_TRUE : VK_FALSE),
|
static_cast<VkBool32>(dynamic.rasterize_enable == 0 ? VK_TRUE : VK_FALSE),
|
||||||
.polygonMode =
|
.polygonMode =
|
||||||
MaxwellToVK::PolygonMode(FixedPipelineState::UnpackPolygonMode(key.state.polygon_mode)),
|
MaxwellToVK::PolygonMode(FixedPipelineState::UnpackPolygonMode(key.state.polygon_mode)),
|
||||||
.cullMode = static_cast<VkCullModeFlags>(
|
.cullMode = static_cast<VkCullModeFlags>(
|
||||||
dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE),
|
dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE),
|
||||||
.frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()),
|
.frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()),
|
||||||
|
@ -740,6 +740,12 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||||
? VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT
|
? VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT
|
||||||
: VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT,
|
: VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT,
|
||||||
};
|
};
|
||||||
|
VkPipelineRasterizationDepthClipStateCreateInfoEXT depth_clip{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.depthClipEnable = VK_TRUE,
|
||||||
|
};
|
||||||
if (IsLine(input_assembly_topology) && device.IsExtLineRasterizationSupported()) {
|
if (IsLine(input_assembly_topology) && device.IsExtLineRasterizationSupported()) {
|
||||||
line_state.pNext = std::exchange(rasterization_ci.pNext, &line_state);
|
line_state.pNext = std::exchange(rasterization_ci.pNext, &line_state);
|
||||||
}
|
}
|
||||||
|
@ -749,6 +755,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||||
if (device.IsExtProvokingVertexSupported()) {
|
if (device.IsExtProvokingVertexSupported()) {
|
||||||
provoking_vertex.pNext = std::exchange(rasterization_ci.pNext, &provoking_vertex);
|
provoking_vertex.pNext = std::exchange(rasterization_ci.pNext, &provoking_vertex);
|
||||||
}
|
}
|
||||||
|
if (device.IsExtDepthClipControlSupported()) {
|
||||||
|
depth_clip.pNext = std::exchange(rasterization_ci.pNext, &depth_clip);
|
||||||
|
}
|
||||||
|
|
||||||
const VkPipelineMultisampleStateCreateInfo multisample_ci{
|
const VkPipelineMultisampleStateCreateInfo multisample_ci{
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||||
|
@ -814,7 +823,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||||
.logicOp = static_cast<VkLogicOp>(dynamic.logic_op.Value()),
|
.logicOp = static_cast<VkLogicOp>(dynamic.logic_op.Value()),
|
||||||
.attachmentCount = static_cast<u32>(cb_attachments.size()),
|
.attachmentCount = static_cast<u32>(cb_attachments.size()),
|
||||||
.pAttachments = cb_attachments.data(),
|
.pAttachments = cb_attachments.data(),
|
||||||
.blendConstants = {},
|
.blendConstants = {}
|
||||||
};
|
};
|
||||||
static_vector<VkDynamicState, 28> dynamic_states{
|
static_vector<VkDynamicState, 28> dynamic_states{
|
||||||
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR,
|
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue