From 8d694701bcd97c3766692dff2a9b4ec2f3a64ebd Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 6 Dec 2022 22:32:59 +0100 Subject: MacroHLE: Add OpenGL Support --- src/video_core/renderer_opengl/gl_rasterizer.cpp | 124 ++++++++++++++++------- 1 file changed, 87 insertions(+), 37 deletions(-) (limited to 'src/video_core/renderer_opengl/gl_rasterizer.cpp') diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index a44b8c454..0807d0b88 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -202,7 +202,8 @@ void RasterizerOpenGL::Clear(u32 layer_count) { ++num_queued_commands; } -void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) { +template +void RasterizerOpenGL::PrepareDraw(bool is_indexed, Func&& draw_func) { MICROPROFILE_SCOPE(OpenGL_Drawing); SCOPE_EXIT({ gpu.TickWork(); }); @@ -226,48 +227,97 @@ void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) { const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(draw_state.topology); BeginTransformFeedback(pipeline, primitive_mode); - const GLuint base_instance = static_cast(draw_state.base_instance); - const GLsizei num_instances = static_cast(instance_count); - if (is_indexed) { - const GLint base_vertex = static_cast(draw_state.base_index); - const GLsizei num_vertices = static_cast(draw_state.index_buffer.count); - const GLvoid* const offset = buffer_cache_runtime.IndexOffset(); - const GLenum format = MaxwellToGL::IndexFormat(draw_state.index_buffer.format); - if (num_instances == 1 && base_instance == 0 && base_vertex == 0) { - glDrawElements(primitive_mode, num_vertices, format, offset); - } else if (num_instances == 1 && base_instance == 0) { - glDrawElementsBaseVertex(primitive_mode, num_vertices, format, offset, base_vertex); - } else if (base_vertex == 0 && base_instance == 0) { - glDrawElementsInstanced(primitive_mode, num_vertices, format, offset, num_instances); - } else if (base_vertex == 0) { - glDrawElementsInstancedBaseInstance(primitive_mode, num_vertices, format, offset, - num_instances, base_instance); - } else if (base_instance == 0) { - glDrawElementsInstancedBaseVertex(primitive_mode, num_vertices, format, offset, - num_instances, base_vertex); - } else { - glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, num_vertices, format, - offset, num_instances, base_vertex, - base_instance); - } - } else { - const GLint base_vertex = static_cast(draw_state.vertex_buffer.first); - const GLsizei num_vertices = static_cast(draw_state.vertex_buffer.count); - if (num_instances == 1 && base_instance == 0) { - glDrawArrays(primitive_mode, base_vertex, num_vertices); - } else if (base_instance == 0) { - glDrawArraysInstanced(primitive_mode, base_vertex, num_vertices, num_instances); - } else { - glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, num_vertices, - num_instances, base_instance); - } - } + draw_func(primitive_mode); + EndTransformFeedback(); ++num_queued_commands; has_written_global_memory |= pipeline->WritesGlobalMemory(); } +void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) { + PrepareDraw(is_indexed, [this, is_indexed, instance_count](GLenum primitive_mode) { + const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); + const GLuint base_instance = static_cast(draw_state.base_instance); + const GLsizei num_instances = static_cast(instance_count); + if (is_indexed) { + const GLint base_vertex = static_cast(draw_state.base_index); + const GLsizei num_vertices = static_cast(draw_state.index_buffer.count); + const GLvoid* const offset = buffer_cache_runtime.IndexOffset(); + const GLenum format = MaxwellToGL::IndexFormat(draw_state.index_buffer.format); + if (num_instances == 1 && base_instance == 0 && base_vertex == 0) { + glDrawElements(primitive_mode, num_vertices, format, offset); + } else if (num_instances == 1 && base_instance == 0) { + glDrawElementsBaseVertex(primitive_mode, num_vertices, format, offset, base_vertex); + } else if (base_vertex == 0 && base_instance == 0) { + glDrawElementsInstanced(primitive_mode, num_vertices, format, offset, + num_instances); + } else if (base_vertex == 0) { + glDrawElementsInstancedBaseInstance(primitive_mode, num_vertices, format, offset, + num_instances, base_instance); + } else if (base_instance == 0) { + glDrawElementsInstancedBaseVertex(primitive_mode, num_vertices, format, offset, + num_instances, base_vertex); + } else { + glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, num_vertices, format, + offset, num_instances, base_vertex, + base_instance); + } + } else { + const GLint base_vertex = static_cast(draw_state.vertex_buffer.first); + const GLsizei num_vertices = static_cast(draw_state.vertex_buffer.count); + if (num_instances == 1 && base_instance == 0) { + glDrawArrays(primitive_mode, base_vertex, num_vertices); + } else if (base_instance == 0) { + glDrawArraysInstanced(primitive_mode, base_vertex, num_vertices, num_instances); + } else { + glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, num_vertices, + num_instances, base_instance); + } + } + }); +} + +void RasterizerOpenGL::DrawIndirect() { + const auto& params = maxwell3d->draw_manager->GetIndirectParams(); + buffer_cache.SetDrawIndirect(¶ms); + PrepareDraw(params.is_indexed, [this, ¶ms](GLenum primitive_mode) { + const auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer(); + const GLvoid* const gl_offset = + reinterpret_cast(static_cast(offset)); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer->Handle()); + if (params.include_count) { + const auto [draw_buffer, offset_base] = buffer_cache.GetDrawIndirectCount(); + glBindBuffer(GL_PARAMETER_BUFFER, draw_buffer->Handle()); + + if (params.is_indexed) { + const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format); + glMultiDrawElementsIndirectCount(primitive_mode, format, gl_offset, + static_cast(offset_base), + static_cast(params.max_draw_counts), + static_cast(params.stride)); + } else { + glMultiDrawArraysIndirectCount(primitive_mode, gl_offset, + static_cast(offset_base), + static_cast(params.max_draw_counts), + static_cast(params.stride)); + } + return; + } + if (params.is_indexed) { + const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format); + glMultiDrawElementsIndirect(primitive_mode, format, gl_offset, + static_cast(params.max_draw_counts), + static_cast(params.stride)); + } else { + glMultiDrawArraysIndirect(primitive_mode, gl_offset, + static_cast(params.max_draw_counts), + static_cast(params.stride)); + } + }); + buffer_cache.SetDrawIndirect(nullptr); +} + void RasterizerOpenGL::DispatchCompute() { ComputePipeline* const pipeline{shader_cache.CurrentComputePipeline()}; if (!pipeline) { -- cgit v1.2.3 From 3630bfaef332768e08ecc0c34cd4bca83a2579f8 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 20 Nov 2022 03:07:14 +0100 Subject: RasterizerMemory: Add filtering for flushing/invalidation operations. --- src/video_core/renderer_opengl/gl_rasterizer.cpp | 51 +++++++++++++++--------- 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'src/video_core/renderer_opengl/gl_rasterizer.cpp') diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 0807d0b88..d58dcedea 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -352,46 +352,60 @@ void RasterizerOpenGL::DisableGraphicsUniformBuffer(size_t stage, u32 index) { void RasterizerOpenGL::FlushAll() {} -void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) { +void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { MICROPROFILE_SCOPE(OpenGL_CacheManagement); if (addr == 0 || size == 0) { return; } - { + if (bool(which & VideoCommon::CacheType::TextureCache)) { std::scoped_lock lock{texture_cache.mutex}; texture_cache.DownloadMemory(addr, size); } - { + if ((bool(which & VideoCommon::CacheType::BufferCache))) { std::scoped_lock lock{buffer_cache.mutex}; buffer_cache.DownloadMemory(addr, size); } - query_cache.FlushRegion(addr, size); + if ((bool(which & VideoCommon::CacheType::QueryCache))) { + query_cache.FlushRegion(addr, size); + } } -bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size) { - std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; +bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { + if ((bool(which & VideoCommon::CacheType::BufferCache))) { + std::scoped_lock lock{buffer_cache.mutex}; + if (buffer_cache.IsRegionGpuModified(addr, size)) { + return true; + } + } if (!Settings::IsGPULevelHigh()) { - return buffer_cache.IsRegionGpuModified(addr, size); + return false; + } + if (bool(which & VideoCommon::CacheType::TextureCache)) { + std::scoped_lock lock{texture_cache.mutex}; + return texture_cache.IsRegionGpuModified(addr, size); } - return texture_cache.IsRegionGpuModified(addr, size) || - buffer_cache.IsRegionGpuModified(addr, size); + return false; } -void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) { +void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { MICROPROFILE_SCOPE(OpenGL_CacheManagement); if (addr == 0 || size == 0) { return; } - { + if (bool(which & VideoCommon::CacheType::TextureCache)) { std::scoped_lock lock{texture_cache.mutex}; texture_cache.WriteMemory(addr, size); } - { + if (bool(which & VideoCommon::CacheType::BufferCache)) { std::scoped_lock lock{buffer_cache.mutex}; buffer_cache.WriteMemory(addr, size); } - shader_cache.InvalidateRegion(addr, size); - query_cache.InvalidateRegion(addr, size); + if (bool(which & VideoCommon::CacheType::ShaderCache)) { + shader_cache.InvalidateRegion(addr, size); + } + if (bool(which & VideoCommon::CacheType::QueryCache)) { + query_cache.InvalidateRegion(addr, size); + } } void RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) { @@ -458,11 +472,12 @@ void RasterizerOpenGL::ReleaseFences() { fence_manager.WaitPendingFences(); } -void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) { +void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size, + VideoCommon::CacheType which) { if (Settings::IsGPULevelExtreme()) { - FlushRegion(addr, size); + FlushRegion(addr, size, which); } - InvalidateRegion(addr, size); + InvalidateRegion(addr, size, which); } void RasterizerOpenGL::WaitForIdle() { @@ -531,7 +546,7 @@ void RasterizerOpenGL::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si } gpu_memory->WriteBlockUnsafe(address, memory.data(), copy_size); { - std::unique_lock lock{buffer_cache.mutex}; + std::unique_lock lock{buffer_cache.mutex}; if (!buffer_cache.InlineMemory(*cpu_addr, copy_size, memory)) { buffer_cache.WriteMemory(*cpu_addr, copy_size); } -- cgit v1.2.3 From 581a7d785bb4936c92d320f17d3d824e244eee5a Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 7 Dec 2022 00:28:35 +0100 Subject: Rasterizer: Setup skeleton for Host Conditional rendering --- src/video_core/renderer_opengl/gl_rasterizer.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/video_core/renderer_opengl/gl_rasterizer.cpp') diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index d58dcedea..ed7558073 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -525,6 +525,21 @@ void RasterizerOpenGL::TickFrame() { } } +bool RasterizerOpenGL::AccelerateConditionalRendering() { + if (Settings::IsGPULevelHigh()) { + // Reimplement Host conditional rendering. + return false; + } + // Medium / Low Hack: stub any checks on queries writen into the buffer cache. + const GPUVAddr condition_address{maxwell3d->regs.render_enable.Address()}; + Maxwell::ReportSemaphore::Compare cmp; + if (gpu_memory->IsMemoryDirty(condition_address, sizeof(cmp), + VideoCommon::CacheType::BufferCache)) { + return true; + } + return false; +} + bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src, const Tegra::Engines::Fermi2D::Surface& dst, const Tegra::Engines::Fermi2D::Config& copy_config) { -- cgit v1.2.3 From a0c697124ced080f58866825e2e323e8682bbd7f Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 3 Jan 2023 10:01:25 -0500 Subject: Video_core: Address feedback --- src/video_core/renderer_opengl/gl_rasterizer.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/video_core/renderer_opengl/gl_rasterizer.cpp') diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index ed7558073..7d48af8e1 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -357,21 +357,21 @@ void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size, VideoCommon::CacheType if (addr == 0 || size == 0) { return; } - if (bool(which & VideoCommon::CacheType::TextureCache)) { + if (True(which & VideoCommon::CacheType::TextureCache)) { std::scoped_lock lock{texture_cache.mutex}; texture_cache.DownloadMemory(addr, size); } - if ((bool(which & VideoCommon::CacheType::BufferCache))) { + if ((True(which & VideoCommon::CacheType::BufferCache))) { std::scoped_lock lock{buffer_cache.mutex}; buffer_cache.DownloadMemory(addr, size); } - if ((bool(which & VideoCommon::CacheType::QueryCache))) { + if ((True(which & VideoCommon::CacheType::QueryCache))) { query_cache.FlushRegion(addr, size); } } bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { - if ((bool(which & VideoCommon::CacheType::BufferCache))) { + if ((True(which & VideoCommon::CacheType::BufferCache))) { std::scoped_lock lock{buffer_cache.mutex}; if (buffer_cache.IsRegionGpuModified(addr, size)) { return true; @@ -380,7 +380,7 @@ bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheT if (!Settings::IsGPULevelHigh()) { return false; } - if (bool(which & VideoCommon::CacheType::TextureCache)) { + if (True(which & VideoCommon::CacheType::TextureCache)) { std::scoped_lock lock{texture_cache.mutex}; return texture_cache.IsRegionGpuModified(addr, size); } @@ -392,18 +392,18 @@ void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size, VideoCommon::Cache if (addr == 0 || size == 0) { return; } - if (bool(which & VideoCommon::CacheType::TextureCache)) { + if (True(which & VideoCommon::CacheType::TextureCache)) { std::scoped_lock lock{texture_cache.mutex}; texture_cache.WriteMemory(addr, size); } - if (bool(which & VideoCommon::CacheType::BufferCache)) { + if (True(which & VideoCommon::CacheType::BufferCache)) { std::scoped_lock lock{buffer_cache.mutex}; buffer_cache.WriteMemory(addr, size); } - if (bool(which & VideoCommon::CacheType::ShaderCache)) { + if (True(which & VideoCommon::CacheType::ShaderCache)) { shader_cache.InvalidateRegion(addr, size); } - if (bool(which & VideoCommon::CacheType::QueryCache)) { + if (True(which & VideoCommon::CacheType::QueryCache)) { query_cache.InvalidateRegion(addr, size); } } -- cgit v1.2.3