diff options
Diffstat (limited to 'src/video_core')
-rw-r--r-- | src/video_core/engines/maxwell_3d.h | 22 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 44 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 3 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.cpp | 31 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.h | 29 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_state_tracker.cpp | 10 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_state_tracker.h | 11 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/maxwell_to_gl.h | 13 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 5 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 9 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp | 3 |
11 files changed, 148 insertions, 32 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 7000b0589..8752a1cfb 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -525,6 +525,12 @@ public: FractionalEven = 2, }; + enum class PolygonMode : u32 { + Point = 0x1b00, + Line = 0x1b01, + Fill = 0x1b02, + }; + struct RenderTargetConfig { u32 address_high; u32 address_low; @@ -728,7 +734,12 @@ public: s32 clear_stencil; - INSERT_UNION_PADDING_WORDS(0x7); + INSERT_UNION_PADDING_WORDS(0x2); + + PolygonMode polygon_mode_front; + PolygonMode polygon_mode_back; + + INSERT_UNION_PADDING_WORDS(0x3); u32 polygon_offset_point_enable; u32 polygon_offset_line_enable; @@ -787,7 +798,11 @@ public: BitField<12, 4, u32> viewport; } clear_flags; - INSERT_UNION_PADDING_WORDS(0x19); + INSERT_UNION_PADDING_WORDS(0x10); + + u32 fill_rectangle; + + INSERT_UNION_PADDING_WORDS(0x8); std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format; @@ -1451,6 +1466,8 @@ ASSERT_REG_POSITION(depth_mode, 0x35F); ASSERT_REG_POSITION(clear_color[0], 0x360); ASSERT_REG_POSITION(clear_depth, 0x364); ASSERT_REG_POSITION(clear_stencil, 0x368); +ASSERT_REG_POSITION(polygon_mode_front, 0x36B); +ASSERT_REG_POSITION(polygon_mode_back, 0x36C); ASSERT_REG_POSITION(polygon_offset_point_enable, 0x370); ASSERT_REG_POSITION(polygon_offset_line_enable, 0x371); ASSERT_REG_POSITION(polygon_offset_fill_enable, 0x372); @@ -1464,6 +1481,7 @@ ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB); ASSERT_REG_POSITION(depth_bounds, 0x3E7); ASSERT_REG_POSITION(zeta, 0x3F8); ASSERT_REG_POSITION(clear_flags, 0x43E); +ASSERT_REG_POSITION(fill_rectangle, 0x44F); ASSERT_REG_POSITION(vertex_attrib_format, 0x458); ASSERT_REG_POSITION(rt_control, 0x487); ASSERT_REG_POSITION(zeta_width, 0x48a); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 385a31ef6..8a2db8e36 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -484,6 +484,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { SyncViewport(); SyncRasterizeEnable(); + SyncPolygonModes(); SyncColorMask(); SyncFragmentColorClampState(); SyncMultiSampleState(); @@ -562,7 +563,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { bind_ubo_pushbuffer.Bind(); bind_ssbo_pushbuffer.Bind(); - program_manager.Update(); + program_manager.BindGraphicsPipeline(); if (texture_cache.TextureBarrier()) { glTextureBarrier(); @@ -619,7 +620,7 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) { auto kernel = shader_cache.GetComputeKernel(code_addr); SetupComputeTextures(kernel); SetupComputeImages(kernel); - glUseProgramStages(program_manager.GetHandle(), GL_COMPUTE_SHADER_BIT, kernel->GetHandle()); + program_manager.BindComputeShader(kernel->GetHandle()); const std::size_t buffer_size = Tegra::Engines::KeplerCompute::NumConstBuffers * @@ -1089,6 +1090,45 @@ void RasterizerOpenGL::SyncRasterizeEnable() { oglEnable(GL_RASTERIZER_DISCARD, gpu.regs.rasterize_enable == 0); } +void RasterizerOpenGL::SyncPolygonModes() { + auto& gpu = system.GPU().Maxwell3D(); + auto& flags = gpu.dirty.flags; + if (!flags[Dirty::PolygonModes]) { + return; + } + flags[Dirty::PolygonModes] = false; + + if (gpu.regs.fill_rectangle) { + if (!GLAD_GL_NV_fill_rectangle) { + LOG_ERROR(Render_OpenGL, "GL_NV_fill_rectangle used and not supported"); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + return; + } + + flags[Dirty::PolygonModeFront] = true; + flags[Dirty::PolygonModeBack] = true; + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_RECTANGLE_NV); + return; + } + + if (gpu.regs.polygon_mode_front == gpu.regs.polygon_mode_back) { + flags[Dirty::PolygonModeFront] = false; + flags[Dirty::PolygonModeBack] = false; + glPolygonMode(GL_FRONT_AND_BACK, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_front)); + return; + } + + if (flags[Dirty::PolygonModeFront]) { + flags[Dirty::PolygonModeFront] = false; + glPolygonMode(GL_FRONT, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_front)); + } + + if (flags[Dirty::PolygonModeBack]) { + flags[Dirty::PolygonModeBack] = false; + glPolygonMode(GL_BACK, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_back)); + } +} + void RasterizerOpenGL::SyncColorMask() { auto& gpu = system.GPU().Maxwell3D(); auto& flags = gpu.dirty.flags; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index e83c5ebdc..e6424f5d2 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -177,6 +177,9 @@ private: /// Syncs the rasterizer enable state to match the guest state void SyncRasterizeEnable(); + /// Syncs polygon modes to match the guest state + void SyncPolygonModes(); + /// Syncs Color Mask void SyncColorMask(); diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 15f3cd066..9c7b0adbd 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp @@ -2,21 +2,29 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <glad/glad.h> + #include "common/common_types.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/renderer_opengl/gl_shader_manager.h" namespace OpenGL::GLShader { -using Tegra::Engines::Maxwell3D; +ProgramManager::ProgramManager() = default; ProgramManager::~ProgramManager() = default; void ProgramManager::Create() { - pipeline.Create(); + graphics_pipeline.Create(); + glBindProgramPipeline(graphics_pipeline.handle); } -void ProgramManager::Update() { +void ProgramManager::BindGraphicsPipeline() { + if (!is_graphics_bound) { + is_graphics_bound = true; + glUseProgram(0); + } + // Avoid updating the pipeline when values have no changed if (old_state == current_state) { return; @@ -25,16 +33,21 @@ void ProgramManager::Update() { // Workaround for AMD bug static constexpr GLenum all_used_stages{GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | GL_FRAGMENT_SHADER_BIT}; - glUseProgramStages(pipeline.handle, all_used_stages, 0); - - glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, current_state.vertex_shader); - glUseProgramStages(pipeline.handle, GL_GEOMETRY_SHADER_BIT, current_state.geometry_shader); - glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, current_state.fragment_shader); + const GLuint handle = graphics_pipeline.handle; + glUseProgramStages(handle, all_used_stages, 0); + glUseProgramStages(handle, GL_VERTEX_SHADER_BIT, current_state.vertex_shader); + glUseProgramStages(handle, GL_GEOMETRY_SHADER_BIT, current_state.geometry_shader); + glUseProgramStages(handle, GL_FRAGMENT_SHADER_BIT, current_state.fragment_shader); old_state = current_state; } -void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell) { +void ProgramManager::BindComputeShader(GLuint program) { + is_graphics_bound = false; + glUseProgram(program); +} + +void MaxwellUniformData::SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell) { const auto& regs = maxwell.regs; // Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value. diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index e94cd75aa..d2e47f2a9 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h @@ -28,11 +28,16 @@ static_assert(sizeof(MaxwellUniformData) < 16384, class ProgramManager { public: + explicit ProgramManager(); ~ProgramManager(); void Create(); - void Update(); + /// Updates the graphics pipeline and binds it. + void BindGraphicsPipeline(); + + /// Binds a compute shader. + void BindComputeShader(GLuint program); void UseVertexShader(GLuint program) { current_state.vertex_shader = program; @@ -46,33 +51,27 @@ public: current_state.fragment_shader = program; } - GLuint GetHandle() const { - return pipeline.handle; - } - - void UseTrivialFragmentShader() { - current_state.fragment_shader = 0; - } - private: struct PipelineState { - bool operator==(const PipelineState& rhs) const { + bool operator==(const PipelineState& rhs) const noexcept { return vertex_shader == rhs.vertex_shader && fragment_shader == rhs.fragment_shader && geometry_shader == rhs.geometry_shader; } - bool operator!=(const PipelineState& rhs) const { + bool operator!=(const PipelineState& rhs) const noexcept { return !operator==(rhs); } - GLuint vertex_shader{}; - GLuint fragment_shader{}; - GLuint geometry_shader{}; + GLuint vertex_shader = 0; + GLuint fragment_shader = 0; + GLuint geometry_shader = 0; }; - OGLPipeline pipeline; + OGLPipeline graphics_pipeline; + OGLPipeline compute_pipeline; PipelineState current_state; PipelineState old_state; + bool is_graphics_bound = true; }; } // namespace OpenGL::GLShader diff --git a/src/video_core/renderer_opengl/gl_state_tracker.cpp b/src/video_core/renderer_opengl/gl_state_tracker.cpp index 1e43c9ec0..3f3bdf812 100644 --- a/src/video_core/renderer_opengl/gl_state_tracker.cpp +++ b/src/video_core/renderer_opengl/gl_state_tracker.cpp @@ -94,6 +94,15 @@ void SetupDirtyShaders(Tables& tables) { Shaders); } +void SetupDirtyPolygonModes(Tables& tables) { + tables[0][OFF(polygon_mode_front)] = PolygonModeFront; + tables[0][OFF(polygon_mode_back)] = PolygonModeBack; + + tables[1][OFF(polygon_mode_front)] = PolygonModes; + tables[1][OFF(polygon_mode_back)] = PolygonModes; + tables[0][OFF(fill_rectangle)] = PolygonModes; +} + void SetupDirtyDepthTest(Tables& tables) { auto& table = tables[0]; table[OFF(depth_test_enable)] = DepthTest; @@ -211,6 +220,7 @@ void StateTracker::Initialize() { SetupDirtyVertexArrays(tables); SetupDirtyVertexFormat(tables); SetupDirtyShaders(tables); + SetupDirtyPolygonModes(tables); SetupDirtyDepthTest(tables); SetupDirtyStencilTest(tables); SetupDirtyAlphaTest(tables); diff --git a/src/video_core/renderer_opengl/gl_state_tracker.h b/src/video_core/renderer_opengl/gl_state_tracker.h index e08482911..b882d75c3 100644 --- a/src/video_core/renderer_opengl/gl_state_tracker.h +++ b/src/video_core/renderer_opengl/gl_state_tracker.h @@ -59,6 +59,10 @@ enum : u8 { Shaders, ClipDistances, + PolygonModes, + PolygonModeFront, + PolygonModeBack, + ColorMask, FrontFace, CullTest, @@ -111,6 +115,13 @@ public: flags[OpenGL::Dirty::VertexInstance0 + 1] = true; } + void NotifyPolygonModes() { + auto& flags = system.GPU().Maxwell3D().dirty.flags; + flags[OpenGL::Dirty::PolygonModes] = true; + flags[OpenGL::Dirty::PolygonModeFront] = true; + flags[OpenGL::Dirty::PolygonModeBack] = true; + } + void NotifyViewport0() { auto& flags = system.GPU().Maxwell3D().dirty.flags; flags[OpenGL::Dirty::Viewports] = true; diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index 494e38e7a..89f0e04ef 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h @@ -488,5 +488,18 @@ inline GLenum LogicOp(Maxwell::LogicOperation operation) { return GL_COPY; } +inline GLenum PolygonMode(Maxwell::PolygonMode polygon_mode) { + switch (polygon_mode) { + case Maxwell::PolygonMode::Point: + return GL_POINT; + case Maxwell::PolygonMode::Line: + return GL_LINE; + case Maxwell::PolygonMode::Fill: + return GL_FILL; + } + UNREACHABLE_MSG("Invalid polygon mode={}", static_cast<int>(polygon_mode)); + return GL_FILL; +} + } // namespace MaxwellToGL } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index a51410660..12333e8c9 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -443,7 +443,6 @@ void RendererOpenGL::InitOpenGLObjects() { // Create program pipeline program_manager.Create(); - glBindProgramPipeline(program_manager.GetHandle()); // Generate VBO handle for drawing vertex_buffer.Create(); @@ -577,6 +576,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { // TODO: Signal state tracker about these changes state_tracker.NotifyScreenDrawVertexArray(); + state_tracker.NotifyPolygonModes(); state_tracker.NotifyViewport0(); state_tracker.NotifyScissor0(); state_tracker.NotifyColorMask0(); @@ -596,7 +596,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { program_manager.UseVertexShader(vertex_program.handle); program_manager.UseGeometryShader(0); program_manager.UseFragmentShader(fragment_program.handle); - program_manager.Update(); + program_manager.BindGraphicsPipeline(); glEnable(GL_CULL_FACE); if (screen_info.display_srgb) { @@ -612,6 +612,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { glDisable(GL_ALPHA_TEST); glDisablei(GL_BLEND, 0); glDisablei(GL_SCISSOR_TEST, 0); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glCullFace(GL_BACK); glFrontFace(GL_CW); glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index b402fb268..2bcb17b56 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -854,7 +854,7 @@ void RasterizerVulkan::SetupGraphicsTextures(const ShaderEntries& entries, std:: void RasterizerVulkan::SetupGraphicsImages(const ShaderEntries& entries, std::size_t stage) { MICROPROFILE_SCOPE(Vulkan_Images); - const auto& gpu = system.GPU().KeplerCompute(); + const auto& gpu = system.GPU().Maxwell3D(); for (const auto& entry : entries.images) { const auto tic = GetTextureInfo(gpu, entry, stage).tic; SetupImage(tic, entry); @@ -915,6 +915,13 @@ void RasterizerVulkan::SetupComputeImages(const ShaderEntries& entries) { void RasterizerVulkan::SetupConstBuffer(const ConstBufferEntry& entry, const Tegra::Engines::ConstBufferInfo& buffer) { + if (!buffer.enabled) { + // Set values to zero to unbind buffers + update_descriptor_queue.AddBuffer(buffer_cache.GetEmptyBuffer(sizeof(float)), 0, + sizeof(float)); + return; + } + // Align the size to avoid bad std140 interactions const std::size_t size = Common::AlignUp(CalculateConstBufferSize(entry, buffer), 4 * sizeof(float)); diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp index 171d78afc..d9ea3cc21 100644 --- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp @@ -73,7 +73,8 @@ VKBuffer* VKStagingBufferPool::TryGetReservedBuffer(std::size_t size, bool host_ VKBuffer& VKStagingBufferPool::CreateStagingBuffer(std::size_t size, bool host_visible) { const auto usage = vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst | - vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndexBuffer; + vk::BufferUsageFlagBits::eUniformBuffer | vk::BufferUsageFlagBits::eStorageBuffer | + vk::BufferUsageFlagBits::eIndexBuffer; const u32 log2 = Common::Log2Ceil64(size); const vk::BufferCreateInfo buffer_ci({}, 1ULL << log2, usage, vk::SharingMode::eExclusive, 0, nullptr); |