summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
authorLiam <byteslice@airmail.cc>2022-11-30 23:16:00 +0100
committerLiam <byteslice@airmail.cc>2022-12-01 15:51:27 +0100
commit3ef006b5abbe78bb2ae423a7cab74d7da2f8bc08 (patch)
treebf0c9ed637dc39faea655fb836b7a48a9f5d28ee /src/video_core
parentMerge pull request #9308 from lat9nq/from-scratch (diff)
downloadyuzu-3ef006b5abbe78bb2ae423a7cab74d7da2f8bc08.tar
yuzu-3ef006b5abbe78bb2ae423a7cab74d7da2f8bc08.tar.gz
yuzu-3ef006b5abbe78bb2ae423a7cab74d7da2f8bc08.tar.bz2
yuzu-3ef006b5abbe78bb2ae423a7cab74d7da2f8bc08.tar.lz
yuzu-3ef006b5abbe78bb2ae423a7cab74d7da2f8bc08.tar.xz
yuzu-3ef006b5abbe78bb2ae423a7cab74d7da2f8bc08.tar.zst
yuzu-3ef006b5abbe78bb2ae423a7cab74d7da2f8bc08.zip
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp37
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp33
2 files changed, 65 insertions, 5 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 3fe04a115..a38060100 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -39,6 +39,7 @@ using Shader::Backend::GLASM::EmitGLASM;
using Shader::Backend::GLSL::EmitGLSL;
using Shader::Backend::SPIRV::EmitSPIRV;
using Shader::Maxwell::ConvertLegacyToGeneric;
+using Shader::Maxwell::GenerateGeometryPassthrough;
using Shader::Maxwell::MergeDualVertexPrograms;
using Shader::Maxwell::TranslateProgram;
using VideoCommon::ComputeEnvironment;
@@ -56,6 +57,17 @@ auto MakeSpan(Container& container) {
return std::span(container.data(), container.size());
}
+Shader::OutputTopology MaxwellToOutputTopology(Maxwell::PrimitiveTopology topology) {
+ switch (topology) {
+ case Maxwell::PrimitiveTopology::Points:
+ return Shader::OutputTopology::PointList;
+ case Maxwell::PrimitiveTopology::LineStrip:
+ return Shader::OutputTopology::LineStrip;
+ default:
+ return Shader::OutputTopology::TriangleStrip;
+ }
+}
+
Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
const Shader::IR::Program& program,
const Shader::IR::Program* previous_program,
@@ -220,6 +232,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
.support_int64 = device.HasShaderInt64(),
.needs_demote_reorder = device.IsAmd(),
.support_snorm_render_buffer = false,
+ .support_viewport_index_layer = device.HasVertexViewportLayer(),
} {
if (use_asynchronous_shaders) {
workers = CreateWorkers();
@@ -314,9 +327,7 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() {
const auto& regs{maxwell3d->regs};
graphics_key.raw = 0;
graphics_key.early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0);
- graphics_key.gs_input_topology.Assign(graphics_key.unique_hashes[4] != 0
- ? regs.draw.topology.Value()
- : Maxwell::PrimitiveTopology{});
+ graphics_key.gs_input_topology.Assign(regs.draw.topology.Value());
graphics_key.tessellation_primitive.Assign(regs.tessellation.params.domain_type.Value());
graphics_key.tessellation_spacing.Assign(regs.tessellation.params.spacing.Value());
graphics_key.tessellation_clockwise.Assign(
@@ -415,7 +426,19 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs;
const bool uses_vertex_a{key.unique_hashes[0] != 0};
const bool uses_vertex_b{key.unique_hashes[1] != 0};
+
+ // Layer passthrough generation for devices without GL_ARB_shader_viewport_layer_array
+ Shader::IR::Program* layer_source_program{};
+
for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
+ const bool is_emulated_stage = layer_source_program != nullptr &&
+ index == static_cast<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);
+ continue;
+ }
if (key.unique_hashes[index] == 0) {
continue;
}
@@ -443,6 +466,10 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
Shader::NumDescriptors(program_vb.info.storage_buffers_descriptors);
programs[index] = MergeDualVertexPrograms(program_va, program_vb, env);
}
+
+ if (programs[index].info.requires_layer_emulation) {
+ layer_source_program = &programs[index];
+ }
}
const u32 glasm_storage_buffer_limit{device.GetMaxGLASMStorageBufferBlocks()};
const bool glasm_use_storage_buffers{total_storage_buffers <= glasm_storage_buffer_limit};
@@ -456,7 +483,9 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
const bool use_glasm{device.UseAssemblyShaders()};
const size_t first_index = uses_vertex_a && uses_vertex_b ? 1 : 0;
for (size_t index = first_index; index < Maxwell::MaxShaderProgram; ++index) {
- if (key.unique_hashes[index] == 0) {
+ const bool is_emulated_stage = layer_source_program != nullptr &&
+ index == static_cast<u32>(Maxwell::ShaderType::Geometry);
+ if (key.unique_hashes[index] == 0 && !is_emulated_stage) {
continue;
}
UNIMPLEMENTED_IF(index == 0);
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index d4b0a542a..150413b04 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -46,6 +46,7 @@ MICROPROFILE_DECLARE(Vulkan_PipelineCache);
namespace {
using Shader::Backend::SPIRV::EmitSPIRV;
using Shader::Maxwell::ConvertLegacyToGeneric;
+using Shader::Maxwell::GenerateGeometryPassthrough;
using Shader::Maxwell::MergeDualVertexPrograms;
using Shader::Maxwell::TranslateProgram;
using VideoCommon::ComputeEnvironment;
@@ -60,6 +61,17 @@ auto MakeSpan(Container& container) {
return std::span(container.data(), container.size());
}
+Shader::OutputTopology MaxwellToOutputTopology(Maxwell::PrimitiveTopology topology) {
+ switch (topology) {
+ case Maxwell::PrimitiveTopology::Points:
+ return Shader::OutputTopology::PointList;
+ case Maxwell::PrimitiveTopology::LineStrip:
+ return Shader::OutputTopology::LineStrip;
+ default:
+ return Shader::OutputTopology::TriangleStrip;
+ }
+}
+
Shader::CompareFunction MaxwellToCompareFunction(Maxwell::ComparisonOp comparison) {
switch (comparison) {
case Maxwell::ComparisonOp::Never_D3D:
@@ -327,6 +339,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
.needs_demote_reorder = driver_id == VK_DRIVER_ID_AMD_PROPRIETARY_KHR ||
driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR,
.support_snorm_render_buffer = true,
+ .support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(),
};
}
@@ -509,7 +522,19 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs;
const bool uses_vertex_a{key.unique_hashes[0] != 0};
const bool uses_vertex_b{key.unique_hashes[1] != 0};
+
+ // Layer passthrough generation for devices without VK_EXT_shader_viewport_index_layer
+ Shader::IR::Program* layer_source_program{};
+
for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
+ const bool is_emulated_stage = layer_source_program != nullptr &&
+ 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);
+ continue;
+ }
if (key.unique_hashes[index] == 0) {
continue;
}
@@ -530,6 +555,10 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
auto program_vb{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)};
programs[index] = MergeDualVertexPrograms(program_va, program_vb, env);
}
+
+ if (programs[index].info.requires_layer_emulation) {
+ layer_source_program = &programs[index];
+ }
}
std::array<const Shader::Info*, Maxwell::MaxShaderStage> infos{};
std::array<vk::ShaderModule, Maxwell::MaxShaderStage> modules;
@@ -538,7 +567,9 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
Shader::Backend::Bindings binding;
for (size_t index = uses_vertex_a && uses_vertex_b ? 1 : 0; index < Maxwell::MaxShaderProgram;
++index) {
- if (key.unique_hashes[index] == 0) {
+ const bool is_emulated_stage = layer_source_program != nullptr &&
+ index == static_cast<u32>(Maxwell::ShaderType::Geometry);
+ if (key.unique_hashes[index] == 0 && !is_emulated_stage) {
continue;
}
UNIMPLEMENTED_IF(index == 0);