diff options
| -rw-r--r-- | src/video_core/engines/draw_manager.cpp | 31 | ||||
| -rw-r--r-- | src/video_core/engines/draw_manager.h | 20 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 1 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 16 | ||||
| -rw-r--r-- | src/video_core/host_shaders/blit_color_float.frag | 13 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/blit_image.cpp | 59 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/blit_image.h | 38 |
7 files changed, 177 insertions, 1 deletions
diff --git a/src/video_core/engines/draw_manager.cpp b/src/video_core/engines/draw_manager.cpp index 2437121ce..2685481f9 100644 --- a/src/video_core/engines/draw_manager.cpp +++ b/src/video_core/engines/draw_manager.cpp | |||
| @@ -51,6 +51,10 @@ void DrawManager::ProcessMethodCall(u32 method, u32 argument) { | |||
| 51 | LOG_WARNING(HW_GPU, "(STUBBED) called"); | 51 | LOG_WARNING(HW_GPU, "(STUBBED) called"); |
| 52 | break; | 52 | break; |
| 53 | } | 53 | } |
| 54 | case MAXWELL3D_REG_INDEX(draw_texture.src_y0): { | ||
| 55 | DrawTexture(); | ||
| 56 | break; | ||
| 57 | } | ||
| 54 | default: | 58 | default: |
| 55 | break; | 59 | break; |
| 56 | } | 60 | } |
| @@ -179,6 +183,33 @@ void DrawManager::DrawIndexSmall(u32 argument) { | |||
| 179 | ProcessDraw(true, 1); | 183 | ProcessDraw(true, 1); |
| 180 | } | 184 | } |
| 181 | 185 | ||
| 186 | void DrawManager::DrawTexture() { | ||
| 187 | const auto& regs{maxwell3d->regs}; | ||
| 188 | draw_texture_state.dst_x0 = static_cast<float>(regs.draw_texture.dst_x0) / 4096.f; | ||
| 189 | draw_texture_state.dst_y0 = static_cast<float>(regs.draw_texture.dst_y0) / 4096.f; | ||
| 190 | const auto dst_width = static_cast<float>(regs.draw_texture.dst_width) / 4096.f; | ||
| 191 | const auto dst_height = static_cast<float>(regs.draw_texture.dst_height) / 4096.f; | ||
| 192 | const bool lower_left{regs.window_origin.mode != | ||
| 193 | Maxwell3D::Regs::WindowOrigin::Mode::UpperLeft}; | ||
| 194 | if (lower_left) { | ||
| 195 | draw_texture_state.dst_y0 -= dst_height; | ||
| 196 | } | ||
| 197 | draw_texture_state.dst_x1 = draw_texture_state.dst_x0 + dst_width; | ||
| 198 | draw_texture_state.dst_y1 = draw_texture_state.dst_y0 + dst_height; | ||
| 199 | draw_texture_state.src_x0 = static_cast<float>(regs.draw_texture.src_x0) / 4096.f; | ||
| 200 | draw_texture_state.src_y0 = static_cast<float>(regs.draw_texture.src_y0) / 4096.f; | ||
| 201 | draw_texture_state.src_x1 = | ||
| 202 | (static_cast<float>(regs.draw_texture.dx_du) / 4294967295.f) * dst_width + | ||
| 203 | draw_texture_state.src_x0; | ||
| 204 | draw_texture_state.src_y1 = | ||
| 205 | (static_cast<float>(regs.draw_texture.dy_dv) / 4294967295.f) * dst_height + | ||
| 206 | draw_texture_state.src_y0; | ||
| 207 | draw_texture_state.src_sampler = regs.draw_texture.src_sampler; | ||
| 208 | draw_texture_state.src_texture = regs.draw_texture.src_texture; | ||
| 209 | |||
| 210 | maxwell3d->rasterizer->DrawTexture(); | ||
| 211 | } | ||
| 212 | |||
| 182 | void DrawManager::UpdateTopology() { | 213 | void DrawManager::UpdateTopology() { |
| 183 | const auto& regs{maxwell3d->regs}; | 214 | const auto& regs{maxwell3d->regs}; |
| 184 | switch (regs.primitive_topology_control) { | 215 | switch (regs.primitive_topology_control) { |
diff --git a/src/video_core/engines/draw_manager.h b/src/video_core/engines/draw_manager.h index 58d1b2d59..7c22c49f1 100644 --- a/src/video_core/engines/draw_manager.h +++ b/src/video_core/engines/draw_manager.h | |||
| @@ -32,6 +32,19 @@ public: | |||
| 32 | std::vector<u8> inline_index_draw_indexes; | 32 | std::vector<u8> inline_index_draw_indexes; |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | struct DrawTextureState { | ||
| 36 | f32 dst_x0; | ||
| 37 | f32 dst_y0; | ||
| 38 | f32 dst_x1; | ||
| 39 | f32 dst_y1; | ||
| 40 | f32 src_x0; | ||
| 41 | f32 src_y0; | ||
| 42 | f32 src_x1; | ||
| 43 | f32 src_y1; | ||
| 44 | u32 src_sampler; | ||
| 45 | u32 src_texture; | ||
| 46 | }; | ||
| 47 | |||
| 35 | struct IndirectParams { | 48 | struct IndirectParams { |
| 36 | bool is_indexed; | 49 | bool is_indexed; |
| 37 | bool include_count; | 50 | bool include_count; |
| @@ -64,6 +77,10 @@ public: | |||
| 64 | return draw_state; | 77 | return draw_state; |
| 65 | } | 78 | } |
| 66 | 79 | ||
| 80 | const DrawTextureState& GetDrawTextureState() const { | ||
| 81 | return draw_texture_state; | ||
| 82 | } | ||
| 83 | |||
| 67 | IndirectParams& GetIndirectParams() { | 84 | IndirectParams& GetIndirectParams() { |
| 68 | return indirect_state; | 85 | return indirect_state; |
| 69 | } | 86 | } |
| @@ -81,6 +98,8 @@ private: | |||
| 81 | 98 | ||
| 82 | void DrawIndexSmall(u32 argument); | 99 | void DrawIndexSmall(u32 argument); |
| 83 | 100 | ||
| 101 | void DrawTexture(); | ||
| 102 | |||
| 84 | void UpdateTopology(); | 103 | void UpdateTopology(); |
| 85 | 104 | ||
| 86 | void ProcessDraw(bool draw_indexed, u32 instance_count); | 105 | void ProcessDraw(bool draw_indexed, u32 instance_count); |
| @@ -89,6 +108,7 @@ private: | |||
| 89 | 108 | ||
| 90 | Maxwell3D* maxwell3d{}; | 109 | Maxwell3D* maxwell3d{}; |
| 91 | State draw_state{}; | 110 | State draw_state{}; |
| 111 | DrawTextureState draw_texture_state{}; | ||
| 92 | IndirectParams indirect_state{}; | 112 | IndirectParams indirect_state{}; |
| 93 | }; | 113 | }; |
| 94 | } // namespace Tegra::Engines | 114 | } // namespace Tegra::Engines |
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index fbfd1ddd2..a0555ef3f 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -149,6 +149,7 @@ bool Maxwell3D::IsMethodExecutable(u32 method) { | |||
| 149 | case MAXWELL3D_REG_INDEX(inline_index_4x8.index0): | 149 | case MAXWELL3D_REG_INDEX(inline_index_4x8.index0): |
| 150 | case MAXWELL3D_REG_INDEX(vertex_array_instance_first): | 150 | case MAXWELL3D_REG_INDEX(vertex_array_instance_first): |
| 151 | case MAXWELL3D_REG_INDEX(vertex_array_instance_subsequent): | 151 | case MAXWELL3D_REG_INDEX(vertex_array_instance_subsequent): |
| 152 | case MAXWELL3D_REG_INDEX(draw_texture.src_y0): | ||
| 152 | case MAXWELL3D_REG_INDEX(wait_for_idle): | 153 | case MAXWELL3D_REG_INDEX(wait_for_idle): |
| 153 | case MAXWELL3D_REG_INDEX(shadow_ram_control): | 154 | case MAXWELL3D_REG_INDEX(shadow_ram_control): |
| 154 | case MAXWELL3D_REG_INDEX(load_mme.instruction_ptr): | 155 | case MAXWELL3D_REG_INDEX(load_mme.instruction_ptr): |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 0b2fd2928..c89969bb4 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -1599,6 +1599,20 @@ public: | |||
| 1599 | }; | 1599 | }; |
| 1600 | static_assert(sizeof(TIRModulationCoeff) == 0x4); | 1600 | static_assert(sizeof(TIRModulationCoeff) == 0x4); |
| 1601 | 1601 | ||
| 1602 | struct DrawTexture { | ||
| 1603 | s32 dst_x0; | ||
| 1604 | s32 dst_y0; | ||
| 1605 | s32 dst_width; | ||
| 1606 | s32 dst_height; | ||
| 1607 | s64 dx_du; | ||
| 1608 | s64 dy_dv; | ||
| 1609 | u32 src_sampler; | ||
| 1610 | u32 src_texture; | ||
| 1611 | s32 src_x0; | ||
| 1612 | s32 src_y0; | ||
| 1613 | }; | ||
| 1614 | static_assert(sizeof(DrawTexture) == 0x30); | ||
| 1615 | |||
| 1602 | struct ReduceColorThreshold { | 1616 | struct ReduceColorThreshold { |
| 1603 | union { | 1617 | union { |
| 1604 | BitField<0, 8, u32> all_hit_once; | 1618 | BitField<0, 8, u32> all_hit_once; |
| @@ -2751,7 +2765,7 @@ public: | |||
| 2751 | u32 reserved_sw_method2; ///< 0x102C | 2765 | u32 reserved_sw_method2; ///< 0x102C |
| 2752 | std::array<TIRModulationCoeff, 5> tir_modulation_coeff; ///< 0x1030 | 2766 | std::array<TIRModulationCoeff, 5> tir_modulation_coeff; ///< 0x1030 |
| 2753 | std::array<u32, 15> spare_nop; ///< 0x1044 | 2767 | std::array<u32, 15> spare_nop; ///< 0x1044 |
| 2754 | INSERT_PADDING_BYTES_NOINIT(0x30); | 2768 | DrawTexture draw_texture; ///< 0x1080 |
| 2755 | std::array<u32, 7> reserved_sw_method3_to_7; ///< 0x10B0 | 2769 | std::array<u32, 7> reserved_sw_method3_to_7; ///< 0x10B0 |
| 2756 | ReduceColorThreshold reduce_color_thresholds_unorm8; ///< 0x10CC | 2770 | ReduceColorThreshold reduce_color_thresholds_unorm8; ///< 0x10CC |
| 2757 | std::array<u32, 4> reserved_sw_method10_to_13; ///< 0x10D0 | 2771 | std::array<u32, 4> reserved_sw_method10_to_13; ///< 0x10D0 |
diff --git a/src/video_core/host_shaders/blit_color_float.frag b/src/video_core/host_shaders/blit_color_float.frag new file mode 100644 index 000000000..c0c832296 --- /dev/null +++ b/src/video_core/host_shaders/blit_color_float.frag | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #version 450 | ||
| 5 | |||
| 6 | layout(binding = 0) uniform sampler2D tex; | ||
| 7 | |||
| 8 | layout(location = 0) in vec2 texcoord; | ||
| 9 | layout(location = 0) out vec4 color; | ||
| 10 | |||
| 11 | void main() { | ||
| 12 | color = textureLod(tex, texcoord, 0); | ||
| 13 | } | ||
diff --git a/src/video_core/renderer_opengl/blit_image.cpp b/src/video_core/renderer_opengl/blit_image.cpp new file mode 100644 index 000000000..9a560a73b --- /dev/null +++ b/src/video_core/renderer_opengl/blit_image.cpp | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | |||
| 6 | #include "video_core/host_shaders/blit_color_float_frag.h" | ||
| 7 | #include "video_core/host_shaders/full_screen_triangle_vert.h" | ||
| 8 | #include "video_core/renderer_opengl/blit_image.h" | ||
| 9 | #include "video_core/renderer_opengl/gl_shader_manager.h" | ||
| 10 | #include "video_core/renderer_opengl/gl_shader_util.h" | ||
| 11 | |||
| 12 | namespace OpenGL { | ||
| 13 | |||
| 14 | BlitImageHelper::BlitImageHelper(ProgramManager& program_manager_) | ||
| 15 | : program_manager(program_manager_), | ||
| 16 | full_screen_vert(CreateProgram(HostShaders::FULL_SCREEN_TRIANGLE_VERT, GL_VERTEX_SHADER)), | ||
| 17 | blit_color_to_color_frag( | ||
| 18 | CreateProgram(HostShaders::BLIT_COLOR_FLOAT_FRAG, GL_FRAGMENT_SHADER)) {} | ||
| 19 | |||
| 20 | BlitImageHelper::~BlitImageHelper() = default; | ||
| 21 | |||
| 22 | void BlitImageHelper::BlitColor(GLuint dst_framebuffer, GLuint src_image_view, GLuint src_sampler, | ||
| 23 | const Region2D& dst_region, const Region2D& src_region, | ||
| 24 | const Extent3D& src_size) { | ||
| 25 | glEnable(GL_CULL_FACE); | ||
| 26 | glDisable(GL_COLOR_LOGIC_OP); | ||
| 27 | glDisable(GL_DEPTH_TEST); | ||
| 28 | glDisable(GL_STENCIL_TEST); | ||
| 29 | glDisable(GL_POLYGON_OFFSET_FILL); | ||
| 30 | glDisable(GL_RASTERIZER_DISCARD); | ||
| 31 | glDisable(GL_ALPHA_TEST); | ||
| 32 | glDisablei(GL_BLEND, 0); | ||
| 33 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||
| 34 | glCullFace(GL_BACK); | ||
| 35 | glFrontFace(GL_CW); | ||
| 36 | glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | ||
| 37 | glDepthRangeIndexed(0, 0.0, 0.0); | ||
| 38 | |||
| 39 | program_manager.BindPresentPrograms(full_screen_vert.handle, blit_color_to_color_frag.handle); | ||
| 40 | glProgramUniform2f(full_screen_vert.handle, 0, | ||
| 41 | static_cast<float>(src_region.end.x - src_region.start.x) / | ||
| 42 | static_cast<float>(src_size.width), | ||
| 43 | static_cast<float>(src_region.end.y - src_region.start.y) / | ||
| 44 | static_cast<float>(src_size.height)); | ||
| 45 | glProgramUniform2f(full_screen_vert.handle, 1, | ||
| 46 | static_cast<float>(src_region.start.x) / static_cast<float>(src_size.width), | ||
| 47 | static_cast<float>(src_region.start.y) / | ||
| 48 | static_cast<float>(src_size.height)); | ||
| 49 | glViewport(std::min(dst_region.start.x, dst_region.end.x), | ||
| 50 | std::min(dst_region.start.y, dst_region.end.y), | ||
| 51 | std::abs(dst_region.end.x - dst_region.start.x), | ||
| 52 | std::abs(dst_region.end.y - dst_region.start.y)); | ||
| 53 | glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst_framebuffer); | ||
| 54 | glBindSampler(0, src_sampler); | ||
| 55 | glBindTextureUnit(0, src_image_view); | ||
| 56 | glClear(GL_COLOR_BUFFER_BIT); | ||
| 57 | glDrawArrays(GL_TRIANGLES, 0, 3); | ||
| 58 | } | ||
| 59 | } // namespace OpenGL | ||
diff --git a/src/video_core/renderer_opengl/blit_image.h b/src/video_core/renderer_opengl/blit_image.h new file mode 100644 index 000000000..5a2b12d16 --- /dev/null +++ b/src/video_core/renderer_opengl/blit_image.h | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <glad/glad.h> | ||
| 7 | |||
| 8 | #include "video_core/engines/fermi_2d.h" | ||
| 9 | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||
| 10 | #include "video_core/texture_cache/types.h" | ||
| 11 | |||
| 12 | namespace OpenGL { | ||
| 13 | |||
| 14 | using VideoCommon::Extent3D; | ||
| 15 | using VideoCommon::Offset2D; | ||
| 16 | using VideoCommon::Region2D; | ||
| 17 | |||
| 18 | class ProgramManager; | ||
| 19 | class Framebuffer; | ||
| 20 | class ImageView; | ||
| 21 | |||
| 22 | class BlitImageHelper { | ||
| 23 | public: | ||
| 24 | explicit BlitImageHelper(ProgramManager& program_manager); | ||
| 25 | ~BlitImageHelper(); | ||
| 26 | |||
| 27 | void BlitColor(GLuint dst_framebuffer, GLuint src_image_view, GLuint src_sampler, | ||
| 28 | const Region2D& dst_region, const Region2D& src_region, | ||
| 29 | const Extent3D& src_size); | ||
| 30 | |||
| 31 | private: | ||
| 32 | ProgramManager& program_manager; | ||
| 33 | |||
| 34 | OGLProgram full_screen_vert; | ||
| 35 | OGLProgram blit_color_to_color_frag; | ||
| 36 | }; | ||
| 37 | |||
| 38 | } // namespace OpenGL | ||