mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-10-26 21:21:07 +01:00
[TEST] Improve the geometry shader handling
This commit is contained in:
parent
1f0605c35d
commit
69cd5ee0d1
7 changed files with 141 additions and 93 deletions
|
|
@ -54,7 +54,7 @@ using VideoCommon::LoadPipelines;
|
|||
using VideoCommon::SerializePipeline;
|
||||
using Context = ShaderContext::Context;
|
||||
|
||||
constexpr u32 CACHE_VERSION = 15;
|
||||
constexpr u32 CACHE_VERSION = 16;
|
||||
|
||||
template <typename Container>
|
||||
auto MakeSpan(Container& container) {
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ using VideoCommon::FileEnvironment;
|
|||
using VideoCommon::GenericEnvironment;
|
||||
using VideoCommon::GraphicsEnvironment;
|
||||
|
||||
constexpr u32 CACHE_VERSION = 18;
|
||||
constexpr u32 CACHE_VERSION = 19;
|
||||
constexpr size_t VULKAN_CACHE_FLUSH_PIPELINES = 128;
|
||||
constexpr size_t VULKAN_CACHE_FLUSH_MIN_SECONDS = 30;
|
||||
constexpr std::array<char, 8> VULKAN_CACHE_MAGIC_NUMBER{'y', 'u', 'z', 'u', 'v', 'k', 'c', 'h'};
|
||||
|
|
@ -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 ||
|
||||
|
|
|
|||
|
|
@ -850,10 +850,15 @@ void RasterizerVulkan::WaitForIdle() {
|
|||
// fragment shaders can still write storage buffers.
|
||||
VkPipelineStageFlags flags =
|
||||
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
|
||||
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
if (device.SupportsTessellationShader()) {
|
||||
flags |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
|
||||
}
|
||||
if (device.SupportsGeometryShader()) {
|
||||
flags |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
|
||||
}
|
||||
if (device.IsExtTransformFeedbackSupported()) {
|
||||
flags |= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -410,6 +410,7 @@ 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 =
|
||||
|
|
@ -458,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{
|
||||
|
|
|
|||
|
|
@ -1023,6 +1023,31 @@ FN_MAX_LIMIT_LIST
|
|||
return features2.features.multiViewport;
|
||||
}
|
||||
|
||||
bool SupportsTessellationShader() const {
|
||||
return features2.features.tessellationShader;
|
||||
}
|
||||
|
||||
bool SupportsGeometryShader() const {
|
||||
return features2.features.geometryShader;
|
||||
}
|
||||
|
||||
VkPipelineStageFlags AttachmentConsumerStages() const {
|
||||
VkPipelineStageFlags stages = VK_PIPELINE_STAGE_VERTEX_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.tessellationShader) {
|
||||
stages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue