[TEST] Geometry shader changes + barrier fixes

This commit is contained in:
CamilleLaVey
2026-08-11 23:07:23 -04:00
parent 9fe8674760
commit a238536d6d
6 changed files with 138 additions and 96 deletions
@@ -72,6 +72,25 @@ Shader::OutputTopology MaxwellToOutputTopology(Maxwell::PrimitiveTopology topolo
}
}
Shader::InputTopology MaxwellToInputTopology(Maxwell::PrimitiveTopology topology) {
switch (topology) {
case Maxwell::PrimitiveTopology::Points:
return Shader::InputTopology::Points;
case Maxwell::PrimitiveTopology::Lines:
case Maxwell::PrimitiveTopology::LineLoop:
case Maxwell::PrimitiveTopology::LineStrip:
return Shader::InputTopology::Lines;
case Maxwell::PrimitiveTopology::LinesAdjacency:
case Maxwell::PrimitiveTopology::LineStripAdjacency:
return Shader::InputTopology::LinesAdjacency;
case Maxwell::PrimitiveTopology::TrianglesAdjacency:
case Maxwell::PrimitiveTopology::TriangleStripAdjacency:
return Shader::InputTopology::TrianglesAdjacency;
default:
return Shader::InputTopology::Triangles;
}
}
Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
const Shader::IR::Program& program,
const Shader::IR::Program* previous_program,
@@ -127,33 +146,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
default:
break;
}
switch (key.gs_input_topology) {
case Maxwell::PrimitiveTopology::Points:
info.input_topology = Shader::InputTopology::Points;
break;
case Maxwell::PrimitiveTopology::Lines:
case Maxwell::PrimitiveTopology::LineLoop:
case Maxwell::PrimitiveTopology::LineStrip:
info.input_topology = Shader::InputTopology::Lines;
break;
case Maxwell::PrimitiveTopology::Triangles:
case Maxwell::PrimitiveTopology::TriangleStrip:
case Maxwell::PrimitiveTopology::TriangleFan:
case Maxwell::PrimitiveTopology::Quads:
case Maxwell::PrimitiveTopology::QuadStrip:
case Maxwell::PrimitiveTopology::Polygon:
case Maxwell::PrimitiveTopology::Patches:
info.input_topology = Shader::InputTopology::Triangles;
break;
case Maxwell::PrimitiveTopology::LinesAdjacency:
case Maxwell::PrimitiveTopology::LineStripAdjacency:
info.input_topology = Shader::InputTopology::LinesAdjacency;
break;
case Maxwell::PrimitiveTopology::TrianglesAdjacency:
case Maxwell::PrimitiveTopology::TriangleStripAdjacency:
info.input_topology = Shader::InputTopology::TrianglesAdjacency;
break;
}
info.input_topology = MaxwellToInputTopology(key.gs_input_topology);
info.glasm_use_storage_buffers = glasm_use_storage_buffers;
return info;
}
@@ -483,8 +476,10 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
&& index == u32(Maxwell::ShaderType::Geometry);
if (key.unique_hashes[index] == 0 && is_emulated_stage) {
auto topology = MaxwellToOutputTopology(key.gs_input_topology);
programs[index] = GenerateGeometryPassthrough(pools.inst, pools.block, host_info,
*layer_source_program, topology);
programs[index] =
GenerateGeometryPassthrough(pools.inst, pools.block, host_info,
*layer_source_program, topology,
MaxwellToInputTopology(key.gs_input_topology));
continue;
}
if (key.unique_hashes[index] == 0) {
@@ -502,13 +497,15 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
if (!uses_vertex_a || index != 1) {
// Normal path
programs[index] = TranslateProgram(pools.inst, pools.block, env, cfg, host_info);
programs[index] = TranslateProgram(pools.inst, pools.block, env, cfg, host_info,
MaxwellToInputTopology(key.gs_input_topology));
total_storage_buffers += Shader::NumDescriptors(programs[index].info.storage_buffers_descriptors);
} else {
// VertexB path when VertexA is present.
auto& program_va{programs[0]};
auto program_vb{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)};
auto program_vb{TranslateProgram(pools.inst, pools.block, env, cfg, host_info,
MaxwellToInputTopology(key.gs_input_topology))};
total_storage_buffers += Shader::NumDescriptors(program_vb.info.storage_buffers_descriptors);
programs[index] = MergeDualVertexPrograms(program_va, program_vb, env);
}
@@ -597,7 +594,8 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
env.Dump(hash, key.unique_hash);
}
auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)};
auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info,
Shader::InputTopology::Points)};
const u32 num_storage_buffers{Shader::NumDescriptors(program.info.storage_buffers_descriptors)};
Shader::RuntimeInfo info;
info.glasm_use_storage_buffers = num_storage_buffers <= device.GetMaxGLASMStorageBufferBlocks();
@@ -152,6 +152,25 @@ Shader::AttributeType AttributeType(const FixedPipelineState& state, size_t inde
return Shader::AttributeType::Disabled;
}
Shader::InputTopology MaxwellToInputTopology(Maxwell::PrimitiveTopology topology) {
switch (topology) {
case Maxwell::PrimitiveTopology::Points:
return Shader::InputTopology::Points;
case Maxwell::PrimitiveTopology::Lines:
case Maxwell::PrimitiveTopology::LineLoop:
case Maxwell::PrimitiveTopology::LineStrip:
return Shader::InputTopology::Lines;
case Maxwell::PrimitiveTopology::LinesAdjacency:
case Maxwell::PrimitiveTopology::LineStripAdjacency:
return Shader::InputTopology::LinesAdjacency;
case Maxwell::PrimitiveTopology::TrianglesAdjacency:
case Maxwell::PrimitiveTopology::TriangleStripAdjacency:
return Shader::InputTopology::TrianglesAdjacency;
default:
return Shader::InputTopology::Triangles;
}
}
Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> programs,
const GraphicsPipelineCacheKey& key,
const Shader::IR::Program& program,
@@ -270,33 +289,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
default:
break;
}
switch (key.state.topology) {
case Maxwell::PrimitiveTopology::Points:
info.input_topology = Shader::InputTopology::Points;
break;
case Maxwell::PrimitiveTopology::Lines:
case Maxwell::PrimitiveTopology::LineLoop:
case Maxwell::PrimitiveTopology::LineStrip:
info.input_topology = Shader::InputTopology::Lines;
break;
case Maxwell::PrimitiveTopology::Triangles:
case Maxwell::PrimitiveTopology::TriangleStrip:
case Maxwell::PrimitiveTopology::TriangleFan:
case Maxwell::PrimitiveTopology::Quads:
case Maxwell::PrimitiveTopology::QuadStrip:
case Maxwell::PrimitiveTopology::Polygon:
case Maxwell::PrimitiveTopology::Patches:
info.input_topology = Shader::InputTopology::Triangles;
break;
case Maxwell::PrimitiveTopology::LinesAdjacency:
case Maxwell::PrimitiveTopology::LineStripAdjacency:
info.input_topology = Shader::InputTopology::LinesAdjacency;
break;
case Maxwell::PrimitiveTopology::TrianglesAdjacency:
case Maxwell::PrimitiveTopology::TriangleStripAdjacency:
info.input_topology = Shader::InputTopology::TrianglesAdjacency;
break;
}
info.input_topology = MaxwellToInputTopology(key.state.topology);
info.force_early_z = key.state.early_z != 0;
info.y_negate = key.state.y_negate != 0;
return info;
@@ -793,8 +786,10 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
index == static_cast<u32>(Maxwell::ShaderType::Geometry);
if (key.unique_hashes[index] == 0 && is_emulated_stage) {
auto topology = MaxwellToOutputTopology(key.state.topology);
programs[index] = GenerateGeometryPassthrough(pools.inst, pools.block, host_info,
*layer_source_program, topology);
programs[index] =
GenerateGeometryPassthrough(pools.inst, pools.block, host_info,
*layer_source_program, topology,
MaxwellToInputTopology(key.state.topology));
continue;
}
if (key.unique_hashes[index] == 0) {
@@ -807,11 +802,13 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset, index == 0);
if (!uses_vertex_a || index != 1) {
// Normal path
programs[index] = TranslateProgram(pools.inst, pools.block, env, cfg, host_info);
programs[index] = TranslateProgram(pools.inst, pools.block, env, cfg, host_info,
MaxwellToInputTopology(key.state.topology));
} else {
// VertexB path when VertexA is present.
auto& program_va{programs[0]};
auto program_vb{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)};
auto program_vb{TranslateProgram(pools.inst, pools.block, env, cfg, host_info,
MaxwellToInputTopology(key.state.topology))};
programs[index] = MergeDualVertexPrograms(program_va, program_vb, env);
}
@@ -957,7 +954,8 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
env.Dump(hash, key.unique_hash);
}
auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)};
auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info,
Shader::InputTopology::Points)};
const VkDriverIdKHR driver_id = device.GetDriverID();
const bool needs_shared_mem_clamp =
driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY ||
@@ -410,8 +410,17 @@ void Scheduler::EndRenderPass()
Record([num_images = num_renderpass_images,
images = renderpass_images,
ranges = renderpass_image_ranges,
consumer_stages = device.AttachmentConsumerStages(),
has_transform_feedback = device.IsExtTransformFeedbackSupported()](
vk::CommandBuffer cmdbuf) {
static constexpr VkAccessFlags SHADER_ACCESS =
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
static constexpr VkAccessFlags COLOR_ACCESS =
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
static constexpr VkAccessFlags DEPTH_STENCIL_ACCESS =
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
std::array<VkImageMemoryBarrier, 9> barriers;
for (size_t i = 0; i < num_images; ++i) {
const VkImageSubresourceRange& range = ranges[i];
@@ -421,24 +430,25 @@ void Scheduler::EndRenderPass()
| VK_IMAGE_ASPECT_STENCIL_BIT)) !=0;
VkAccessFlags src_access = 0;
VkAccessFlags dst_access = SHADER_ACCESS;
if (is_color)
if (is_color) {
src_access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
else if (is_depth_stencil)
dst_access |= COLOR_ACCESS;
} else if (is_depth_stencil) {
src_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
else
dst_access |= DEPTH_STENCIL_ACCESS;
} else {
src_access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dst_access |= COLOR_ACCESS | DEPTH_STENCIL_ACCESS;
}
barriers[i] = VkImageMemoryBarrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = src_access,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccessMask = dst_access,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -449,7 +459,7 @@ void Scheduler::EndRenderPass()
}
cmdbuf.EndRenderPass();
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, consumer_stages,
0, nullptr, nullptr, vk::Span(barriers.data(), num_images));
if (has_transform_feedback) {
static constexpr VkMemoryBarrier XFB_OUTPUT_BARRIER{
@@ -961,6 +961,21 @@ FN_MAX_LIMIT_LIST
return features2.features.multiViewport;
}
VkPipelineStageFlags AttachmentConsumerStages() const {
VkPipelineStageFlags stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
if (features2.features.geometryShader) {
stages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
}
return stages;
}
/// Returns true if the device supports VK_KHR_maintenance1.
bool IsKhrMaintenance1Supported() const {
return extensions.maintenance1;