From bbfad79c89f9b7886005d39b51129bcfd94830b8 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Tue, 2 Aug 2022 17:41:41 +0100 Subject: Vulkan: Add a workaround for input_position on Adreno drivers Adreno drivers will crash compiling geometry shaders if the input position is not wrapped in a gl_in struct. --- src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/video_core') diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 67e5bc648..4d7770bf8 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -331,6 +331,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device .need_declared_frag_colors = false, .has_broken_spirv_clamp = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS, + .has_broken_spirv_position_input = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY, .has_broken_unsigned_image_offsets = false, .has_broken_signed_operations = false, .has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY, -- cgit v1.2.3 From 9e2997c4b6456031622602002924617690e32a13 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sun, 1 Jan 2023 13:23:24 +0000 Subject: Vulkan, OpenGL: Hook up storage buffer alignment code --- src/video_core/buffer_cache/buffer_cache.h | 12 +++++++++--- src/video_core/renderer_opengl/gl_buffer_cache.h | 4 ++++ src/video_core/renderer_opengl/gl_shader_cache.cpp | 1 + src/video_core/renderer_vulkan/vk_buffer_cache.cpp | 4 ++++ src/video_core/renderer_vulkan/vk_buffer_cache.h | 2 ++ src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 1 + 6 files changed, 21 insertions(+), 3 deletions(-) (limited to 'src/video_core') diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 06fd40851..e6414df78 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1938,14 +1938,20 @@ typename BufferCache

::Binding BufferCache

::StorageBufferBinding(GPUVAddr s bool is_written) const { const GPUVAddr gpu_addr = gpu_memory->Read(ssbo_addr); const u32 size = gpu_memory->Read(ssbo_addr + 8); - const std::optional cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); + const u32 alignment = runtime.GetStorageBufferAlignment(); + + const GPUVAddr aligned_gpu_addr = Common::AlignDown(gpu_addr, alignment); + const u32 aligned_size = Common::AlignUp(static_cast(gpu_addr - aligned_gpu_addr) + size, alignment); + + const std::optional cpu_addr = gpu_memory->GpuToCpuAddress(aligned_gpu_addr); if (!cpu_addr || size == 0) { return NULL_BINDING; } - const VAddr cpu_end = Common::AlignUp(*cpu_addr + size, Core::Memory::YUZU_PAGESIZE); + + const VAddr cpu_end = Common::AlignUp(*cpu_addr + aligned_size, Core::Memory::YUZU_PAGESIZE); const Binding binding{ .cpu_addr = *cpu_addr, - .size = is_written ? size : static_cast(cpu_end - *cpu_addr), + .size = is_written ? aligned_size : static_cast(cpu_end - *cpu_addr), .buffer_id = BufferId{}, }; return binding; diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index a8c3f8b67..bb1962073 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h @@ -160,6 +160,10 @@ public: return device.CanReportMemoryUsage(); } + u32 GetStorageBufferAlignment() const { + return static_cast(device.GetShaderStorageBufferAlignment()); + } + private: static constexpr std::array PABO_LUT{ GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV, GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV, diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 03b6314ff..01e0cddb6 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -236,6 +236,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo .needs_demote_reorder = device.IsAmd(), .support_snorm_render_buffer = false, .support_viewport_index_layer = device.HasVertexViewportLayer(), + .min_ssbo_alignment = static_cast(device.GetShaderStorageBufferAlignment()), } { if (use_asynchronous_shaders) { workers = CreateWorkers(); diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 487d8b416..bc78287ce 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -330,6 +330,10 @@ bool BufferCacheRuntime::CanReportMemoryUsage() const { return device.CanReportMemoryUsage(); } +u32 BufferCacheRuntime::GetStorageBufferAlignment() const { + return static_cast(device.GetStorageBufferAlignment()); +} + void BufferCacheRuntime::Finish() { scheduler.Finish(); } diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 183b33632..06539c733 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -73,6 +73,8 @@ public: bool CanReportMemoryUsage() const; + u32 GetStorageBufferAlignment() const; + [[nodiscard]] StagingBufferRef UploadStagingBuffer(size_t size); [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 4d7770bf8..4aaea0e12 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -344,6 +344,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE, .support_snorm_render_buffer = true, .support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(), + .min_ssbo_alignment = static_cast(device.GetStorageBufferAlignment()), }; if (device.GetMaxVertexInputAttributes() < Maxwell::NumVertexAttributes) { -- cgit v1.2.3 From 6c812a0c84d6fb2f7ffe1d64044be8aeaa905300 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sun, 1 Jan 2023 13:35:23 +0000 Subject: Vulkan, OpenGL: Hook up geometry shader passthrough emulation --- src/video_core/renderer_opengl/gl_shader_cache.cpp | 1 + src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 1 + 2 files changed, 2 insertions(+) (limited to 'src/video_core') diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 01e0cddb6..7dd854e0f 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -237,6 +237,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo .support_snorm_render_buffer = false, .support_viewport_index_layer = device.HasVertexViewportLayer(), .min_ssbo_alignment = static_cast(device.GetShaderStorageBufferAlignment()), + .support_geometry_shader_passthrough = device.HasGeometryShaderPassthrough(), } { if (use_asynchronous_shaders) { workers = CreateWorkers(); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 4aaea0e12..013b42cf8 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -345,6 +345,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device .support_snorm_render_buffer = true, .support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(), .min_ssbo_alignment = static_cast(device.GetStorageBufferAlignment()), + .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), }; if (device.GetMaxVertexInputAttributes() < Maxwell::NumVertexAttributes) { -- cgit v1.2.3 From 58fec43768c837c63453e87df8f337a2d139324a Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Thu, 5 Jan 2023 22:10:21 +0000 Subject: Run clang-format --- .../backend/spirv/emit_spirv_context_get_set.cpp | 11 ++++---- .../backend/spirv/spirv_emit_context.cpp | 5 ++-- .../frontend/maxwell/translate_program.cpp | 32 +++++++++++++--------- src/shader_recompiler/host_translate_info.h | 5 ++-- .../global_memory_to_storage_buffer_pass.cpp | 3 +- src/video_core/buffer_cache/buffer_cache.h | 3 +- 6 files changed, 35 insertions(+), 24 deletions(-) (limited to 'src/video_core') diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 1590debc4..0cd87a48f 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -321,11 +321,12 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { case IR::Attribute::PositionY: case IR::Attribute::PositionZ: case IR::Attribute::PositionW: - return ctx.OpLoad(ctx.F32[1], ctx.need_input_position_indirect ? - AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_position, - ctx.u32_zero_value, ctx.Const(element)) - : AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_position, - ctx.Const(element))); + return ctx.OpLoad( + ctx.F32[1], + ctx.need_input_position_indirect + ? AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_position, ctx.u32_zero_value, + ctx.Const(element)) + : AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_position, ctx.Const(element))); case IR::Attribute::InstanceId: if (ctx.profile.support_vertex_instance_id) { return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.instance_id)); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index f874622b8..a0c155fdb 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -729,7 +729,7 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { else return OpAccessChain(input_f32, input_position, u32_zero_value, masked_index); - } else { + } else { if (is_array) return OpAccessChain(input_f32, input_position, vertex, masked_index); else @@ -1390,7 +1390,8 @@ void EmitContext::DefineInputs(const IR::Program& program) { static_cast(spv::BuiltIn::Position)); Decorate(input_position_struct, spv::Decoration::Block); } else { - const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::FragCoord : spv::BuiltIn::Position}; + const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::FragCoord + : spv::BuiltIn::Position}; input_position = DefineInput(*this, F32[4], true, built_in); if (profile.support_geometry_shader_passthrough) { diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp index 4a0ccceb7..a3b99e24d 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp @@ -172,7 +172,10 @@ std::map GenerateLegacyToGenericMappings( return mapping; } -void EmitGeometryPassthrough(IR::IREmitter& ir, const IR::Program& program, const Shader::VaryingState &passthrough_mask, bool passthrough_position, std::optional passthrough_layer_attr) { +void EmitGeometryPassthrough(IR::IREmitter& ir, const IR::Program& program, + const Shader::VaryingState& passthrough_mask, + bool passthrough_position, + std::optional passthrough_layer_attr) { for (u32 i = 0; i < program.output_vertices; i++) { // Assign generics from input for (u32 j = 0; j < 32; j++) { @@ -198,7 +201,8 @@ void EmitGeometryPassthrough(IR::IREmitter& ir, const IR::Program& program, cons if (passthrough_layer_attr) { // Assign layer - ir.SetAttribute(IR::Attribute::Layer, ir.GetAttribute(*passthrough_layer_attr), ir.Imm32(0)); + ir.SetAttribute(IR::Attribute::Layer, ir.GetAttribute(*passthrough_layer_attr), + ir.Imm32(0)); } // Emit vertex @@ -209,21 +213,23 @@ void EmitGeometryPassthrough(IR::IREmitter& ir, const IR::Program& program, cons u32 GetOutputTopologyVertices(OutputTopology output_topology) { switch (output_topology) { - case OutputTopology::PointList: - return 1; - case OutputTopology::LineStrip: - return 2; - default: - return 3; + case OutputTopology::PointList: + return 1; + case OutputTopology::LineStrip: + return 2; + default: + return 3; } } void LowerGeometryPassthrough(const IR::Program& program, const HostTranslateInfo& host_info) { - for (IR::Block *const block : program.blocks) { - for (IR::Inst &inst : block->Instructions()) { + for (IR::Block* const block : program.blocks) { + for (IR::Inst& inst : block->Instructions()) { if (inst.GetOpcode() == IR::Opcode::Epilogue) { IR::IREmitter ir{*block, IR::Block::InstructionList::s_iterator_to(inst)}; - EmitGeometryPassthrough(ir, program, program.info.passthrough, program.info.passthrough.AnyComponent(IR::Attribute::PositionX), {}); + EmitGeometryPassthrough( + ir, program, program.info.passthrough, + program.info.passthrough.AnyComponent(IR::Attribute::PositionX), {}); } } } @@ -407,7 +413,6 @@ IR::Program GenerateGeometryPassthrough(ObjectPool& inst_pool, program.output_topology = output_topology; program.output_vertices = GetOutputTopologyVertices(output_topology); - program.is_geometry_passthrough = false; program.info.loads.mask = source_program.info.stores.mask; program.info.stores.mask = source_program.info.stores.mask; @@ -420,7 +425,8 @@ IR::Program GenerateGeometryPassthrough(ObjectPool& inst_pool, node.data.block = current_block; IR::IREmitter ir{*current_block}; - EmitGeometryPassthrough(ir, program, program.info.stores, true, source_program.info.emulated_layer); + EmitGeometryPassthrough(ir, program, program.info.stores, true, + source_program.info.emulated_layer); IR::Block* return_block{block_pool.Create(inst_pool)}; IR::IREmitter{*return_block}.Epilogue(); diff --git a/src/shader_recompiler/host_translate_info.h b/src/shader_recompiler/host_translate_info.h index dc402ee47..55fc48768 100644 --- a/src/shader_recompiler/host_translate_info.h +++ b/src/shader_recompiler/host_translate_info.h @@ -15,8 +15,9 @@ struct HostTranslateInfo { bool needs_demote_reorder{}; ///< True when the device needs DemoteToHelperInvocation reordered bool support_snorm_render_buffer{}; ///< True when the device supports SNORM render buffers bool support_viewport_index_layer{}; ///< True when the device supports gl_Layer in VS - u32 min_ssbo_alignment{}; ///< Minimum alignment supported by the device for SSBOs - bool support_geometry_shader_passthrough{}; ///< True when the device supports geometry passthrough shaders + u32 min_ssbo_alignment{}; ///< Minimum alignment supported by the device for SSBOs + bool support_geometry_shader_passthrough{}; ///< True when the device supports geometry + ///< passthrough shaders }; } // namespace Shader diff --git a/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp b/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp index f8d20af3c..9101722ba 100644 --- a/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp +++ b/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp @@ -538,7 +538,8 @@ void GlobalMemoryToStorageBufferPass(IR::Program& program, const HostTranslateIn const IR::U32 index{IR::Value{static_cast(info.set.index_of(it))}}; IR::Block* const block{storage_inst.block}; IR::Inst* const inst{storage_inst.inst}; - const IR::U32 offset{StorageOffset(*block, *inst, storage_buffer, host_info.min_ssbo_alignment)}; + const IR::U32 offset{ + StorageOffset(*block, *inst, storage_buffer, host_info.min_ssbo_alignment)}; Replace(*block, *inst, index, offset); } } diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index e6414df78..627917ab6 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1941,7 +1941,8 @@ typename BufferCache

::Binding BufferCache

::StorageBufferBinding(GPUVAddr s const u32 alignment = runtime.GetStorageBufferAlignment(); const GPUVAddr aligned_gpu_addr = Common::AlignDown(gpu_addr, alignment); - const u32 aligned_size = Common::AlignUp(static_cast(gpu_addr - aligned_gpu_addr) + size, alignment); + const u32 aligned_size = + Common::AlignUp(static_cast(gpu_addr - aligned_gpu_addr) + size, alignment); const std::optional cpu_addr = gpu_memory->GpuToCpuAddress(aligned_gpu_addr); if (!cpu_addr || size == 0) { -- cgit v1.2.3