diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/gsp_gpu.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/pica.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 13 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 30 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 3 | ||||
| -rw-r--r-- | src/video_core/shader/shader_jit_x64.cpp | 17 |
6 files changed, 40 insertions, 27 deletions
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 710e0e485..78cb761be 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp | |||
| @@ -346,7 +346,7 @@ static void SetAxiConfigQoSMode(Service::Interface* self) { | |||
| 346 | 346 | ||
| 347 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 347 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 348 | 348 | ||
| 349 | LOG_WARNING(Service_GSP, "(STUBBED) called mode=0x%08X", mode); | 349 | LOG_DEBUG(Service_GSP, "(STUBBED) called mode=0x%08X", mode); |
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | /** | 352 | /** |
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 99bd59a69..b2db609ec 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h | |||
| @@ -40,7 +40,7 @@ namespace Pica { | |||
| 40 | // field offset. Otherwise, the compiler will fail to compile this code. | 40 | // field offset. Otherwise, the compiler will fail to compile this code. |
| 41 | #define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ | 41 | #define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ |
| 42 | ((typename std::enable_if<backup_workaround_index == PICA_REG_INDEX(field_name), \ | 42 | ((typename std::enable_if<backup_workaround_index == PICA_REG_INDEX(field_name), \ |
| 43 | size_t>::type) PICA_REG_INDEX(field_name)) | 43 | size_t>::type)PICA_REG_INDEX(field_name)) |
| 44 | #endif // _MSC_VER | 44 | #endif // _MSC_VER |
| 45 | 45 | ||
| 46 | struct Regs { | 46 | struct Regs { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 1b734aaa5..3f2255e06 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -715,7 +715,11 @@ bool RasterizerOpenGL::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransfe | |||
| 715 | 715 | ||
| 716 | CachedSurface src_params; | 716 | CachedSurface src_params; |
| 717 | src_params.addr = config.GetPhysicalInputAddress(); | 717 | src_params.addr = config.GetPhysicalInputAddress(); |
| 718 | src_params.width = config.output_width; | 718 | // It's important to use the correct source input width to properly skip over parts of the input |
| 719 | // image which will be cropped from the output but still affect the stride of the input image. | ||
| 720 | src_params.width = config.input_width; | ||
| 721 | // Using the output's height is fine because we don't read or skip over the remaining part of | ||
| 722 | // the image, and it allows for smaller texture cache lookup rectangles. | ||
| 719 | src_params.height = config.output_height; | 723 | src_params.height = config.output_height; |
| 720 | src_params.is_tiled = !config.input_linear; | 724 | src_params.is_tiled = !config.input_linear; |
| 721 | src_params.pixel_format = CachedSurface::PixelFormatFromGPUPixelFormat(config.input_format); | 725 | src_params.pixel_format = CachedSurface::PixelFormatFromGPUPixelFormat(config.input_format); |
| @@ -736,6 +740,11 @@ bool RasterizerOpenGL::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransfe | |||
| 736 | return false; | 740 | return false; |
| 737 | } | 741 | } |
| 738 | 742 | ||
| 743 | // Adjust the source rectangle to take into account parts of the input lines being cropped | ||
| 744 | if (config.input_width > config.output_width) { | ||
| 745 | src_rect.right -= (config.input_width - config.output_width) * src_surface->res_scale_width; | ||
| 746 | } | ||
| 747 | |||
| 739 | // Require destination surface to have same resolution scale as source to preserve scaling | 748 | // Require destination surface to have same resolution scale as source to preserve scaling |
| 740 | dst_params.res_scale_width = src_surface->res_scale_width; | 749 | dst_params.res_scale_width = src_surface->res_scale_width; |
| 741 | dst_params.res_scale_height = src_surface->res_scale_height; | 750 | dst_params.res_scale_height = src_surface->res_scale_height; |
| @@ -938,7 +947,7 @@ bool RasterizerOpenGL::AccelerateDisplay(const GPU::Regs::FramebufferConfig& con | |||
| 938 | src_params.addr = framebuffer_addr; | 947 | src_params.addr = framebuffer_addr; |
| 939 | src_params.width = config.width; | 948 | src_params.width = config.width; |
| 940 | src_params.height = config.height; | 949 | src_params.height = config.height; |
| 941 | src_params.stride = pixel_stride; | 950 | src_params.pixel_stride = pixel_stride; |
| 942 | src_params.is_tiled = false; | 951 | src_params.is_tiled = false; |
| 943 | src_params.pixel_format = CachedSurface::PixelFormatFromGPUPixelFormat(config.color_format); | 952 | src_params.pixel_format = CachedSurface::PixelFormatFromGPUPixelFormat(config.color_format); |
| 944 | 953 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 5cbad9b43..61f6e767f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -158,24 +158,21 @@ bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex, | |||
| 158 | buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; | 158 | buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | if (OpenGLState::CheckFBStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { | 161 | bool can_blit = OpenGLState::CheckFBStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE && |
| 162 | return false; | 162 | OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE; |
| 163 | } | ||
| 164 | 163 | ||
| 165 | if (OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { | 164 | if (can_blit) { |
| 166 | return false; | 165 | glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, |
| 166 | dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, buffers, | ||
| 167 | buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); | ||
| 167 | } | 168 | } |
| 168 | 169 | ||
| 169 | glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, dst_rect.left, | ||
| 170 | dst_rect.top, dst_rect.right, dst_rect.bottom, buffers, | ||
| 171 | buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); | ||
| 172 | |||
| 173 | // Restore previous framebuffer bindings | 170 | // Restore previous framebuffer bindings |
| 174 | cur_state.draw.read_framebuffer = old_fbs[0]; | 171 | cur_state.draw.read_framebuffer = old_fbs[0]; |
| 175 | cur_state.draw.draw_framebuffer = old_fbs[1]; | 172 | cur_state.draw.draw_framebuffer = old_fbs[1]; |
| 176 | cur_state.Apply(); | 173 | cur_state.Apply(); |
| 177 | 174 | ||
| 178 | return true; | 175 | return can_blit; |
| 179 | } | 176 | } |
| 180 | 177 | ||
| 181 | bool RasterizerCacheOpenGL::TryBlitSurfaces(CachedSurface* src_surface, | 178 | bool RasterizerCacheOpenGL::TryBlitSurfaces(CachedSurface* src_surface, |
| @@ -291,6 +288,9 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo | |||
| 291 | 288 | ||
| 292 | MICROPROFILE_SCOPE(OpenGL_SurfaceUpload); | 289 | MICROPROFILE_SCOPE(OpenGL_SurfaceUpload); |
| 293 | 290 | ||
| 291 | // Stride only applies to linear images. | ||
| 292 | ASSERT(params.pixel_stride == 0 || !params.is_tiled); | ||
| 293 | |||
| 294 | std::shared_ptr<CachedSurface> new_surface = std::make_shared<CachedSurface>(); | 294 | std::shared_ptr<CachedSurface> new_surface = std::make_shared<CachedSurface>(); |
| 295 | 295 | ||
| 296 | new_surface->addr = params.addr; | 296 | new_surface->addr = params.addr; |
| @@ -299,7 +299,7 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo | |||
| 299 | new_surface->texture.Create(); | 299 | new_surface->texture.Create(); |
| 300 | new_surface->width = params.width; | 300 | new_surface->width = params.width; |
| 301 | new_surface->height = params.height; | 301 | new_surface->height = params.height; |
| 302 | new_surface->stride = params.stride; | 302 | new_surface->pixel_stride = params.pixel_stride; |
| 303 | new_surface->res_scale_width = params.res_scale_width; | 303 | new_surface->res_scale_width = params.res_scale_width; |
| 304 | new_surface->res_scale_height = params.res_scale_height; | 304 | new_surface->res_scale_height = params.res_scale_height; |
| 305 | 305 | ||
| @@ -325,14 +325,15 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo | |||
| 325 | cur_state.Apply(); | 325 | cur_state.Apply(); |
| 326 | glActiveTexture(GL_TEXTURE0); | 326 | glActiveTexture(GL_TEXTURE0); |
| 327 | 327 | ||
| 328 | glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)new_surface->stride); | ||
| 329 | if (!new_surface->is_tiled) { | 328 | if (!new_surface->is_tiled) { |
| 330 | // TODO: Ensure this will always be a color format, not a depth or other format | 329 | // TODO: Ensure this will always be a color format, not a depth or other format |
| 331 | ASSERT((size_t)new_surface->pixel_format < fb_format_tuples.size()); | 330 | ASSERT((size_t)new_surface->pixel_format < fb_format_tuples.size()); |
| 332 | const FormatTuple& tuple = fb_format_tuples[(unsigned int)params.pixel_format]; | 331 | const FormatTuple& tuple = fb_format_tuples[(unsigned int)params.pixel_format]; |
| 333 | 332 | ||
| 333 | glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)new_surface->pixel_stride); | ||
| 334 | glTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format, params.width, params.height, 0, | 334 | glTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format, params.width, params.height, 0, |
| 335 | tuple.format, tuple.type, texture_src_data); | 335 | tuple.format, tuple.type, texture_src_data); |
| 336 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | ||
| 336 | } else { | 337 | } else { |
| 337 | SurfaceType type = CachedSurface::GetFormatType(new_surface->pixel_format); | 338 | SurfaceType type = CachedSurface::GetFormatType(new_surface->pixel_format); |
| 338 | if (type != SurfaceType::Depth && type != SurfaceType::DepthStencil) { | 339 | if (type != SurfaceType::Depth && type != SurfaceType::DepthStencil) { |
| @@ -391,7 +392,6 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo | |||
| 391 | 0, tuple.format, tuple.type, temp_fb_depth_buffer.data()); | 392 | 0, tuple.format, tuple.type, temp_fb_depth_buffer.data()); |
| 392 | } | 393 | } |
| 393 | } | 394 | } |
| 394 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | ||
| 395 | 395 | ||
| 396 | // If not 1x scale, blit 1x texture to a new scaled texture and replace texture in surface | 396 | // If not 1x scale, blit 1x texture to a new scaled texture and replace texture in surface |
| 397 | if (new_surface->res_scale_width != 1.f || new_surface->res_scale_height != 1.f) { | 397 | if (new_surface->res_scale_width != 1.f || new_surface->res_scale_height != 1.f) { |
| @@ -701,13 +701,14 @@ void RasterizerCacheOpenGL::FlushSurface(CachedSurface* surface) { | |||
| 701 | cur_state.Apply(); | 701 | cur_state.Apply(); |
| 702 | glActiveTexture(GL_TEXTURE0); | 702 | glActiveTexture(GL_TEXTURE0); |
| 703 | 703 | ||
| 704 | glPixelStorei(GL_PACK_ROW_LENGTH, (GLint)surface->stride); | ||
| 705 | if (!surface->is_tiled) { | 704 | if (!surface->is_tiled) { |
| 706 | // TODO: Ensure this will always be a color format, not a depth or other format | 705 | // TODO: Ensure this will always be a color format, not a depth or other format |
| 707 | ASSERT((size_t)surface->pixel_format < fb_format_tuples.size()); | 706 | ASSERT((size_t)surface->pixel_format < fb_format_tuples.size()); |
| 708 | const FormatTuple& tuple = fb_format_tuples[(unsigned int)surface->pixel_format]; | 707 | const FormatTuple& tuple = fb_format_tuples[(unsigned int)surface->pixel_format]; |
| 709 | 708 | ||
| 709 | glPixelStorei(GL_PACK_ROW_LENGTH, (GLint)surface->pixel_stride); | ||
| 710 | glGetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type, dst_buffer); | 710 | glGetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type, dst_buffer); |
| 711 | glPixelStorei(GL_PACK_ROW_LENGTH, 0); | ||
| 711 | } else { | 712 | } else { |
| 712 | SurfaceType type = CachedSurface::GetFormatType(surface->pixel_format); | 713 | SurfaceType type = CachedSurface::GetFormatType(surface->pixel_format); |
| 713 | if (type != SurfaceType::Depth && type != SurfaceType::DepthStencil) { | 714 | if (type != SurfaceType::Depth && type != SurfaceType::DepthStencil) { |
| @@ -750,7 +751,6 @@ void RasterizerCacheOpenGL::FlushSurface(CachedSurface* surface) { | |||
| 750 | false); | 751 | false); |
| 751 | } | 752 | } |
| 752 | } | 753 | } |
| 753 | glPixelStorei(GL_PACK_ROW_LENGTH, 0); | ||
| 754 | 754 | ||
| 755 | surface->dirty = false; | 755 | surface->dirty = false; |
| 756 | 756 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 849530d86..32abfbaf5 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h | |||
| @@ -171,7 +171,8 @@ struct CachedSurface { | |||
| 171 | OGLTexture texture; | 171 | OGLTexture texture; |
| 172 | u32 width; | 172 | u32 width; |
| 173 | u32 height; | 173 | u32 height; |
| 174 | u32 stride = 0; | 174 | /// Stride between lines, in pixels. Only valid for images in linear format. |
| 175 | u32 pixel_stride = 0; | ||
| 175 | float res_scale_width = 1.f; | 176 | float res_scale_width = 1.f; |
| 176 | float res_scale_height = 1.f; | 177 | float res_scale_height = 1.f; |
| 177 | 178 | ||
diff --git a/src/video_core/shader/shader_jit_x64.cpp b/src/video_core/shader/shader_jit_x64.cpp index 211c703ab..c96110bb2 100644 --- a/src/video_core/shader/shader_jit_x64.cpp +++ b/src/video_core/shader/shader_jit_x64.cpp | |||
| @@ -102,11 +102,11 @@ static const X64Reg SETUP = R9; | |||
| 102 | /// The two 32-bit VS address offset registers set by the MOVA instruction | 102 | /// The two 32-bit VS address offset registers set by the MOVA instruction |
| 103 | static const X64Reg ADDROFFS_REG_0 = R10; | 103 | static const X64Reg ADDROFFS_REG_0 = R10; |
| 104 | static const X64Reg ADDROFFS_REG_1 = R11; | 104 | static const X64Reg ADDROFFS_REG_1 = R11; |
| 105 | /// VS loop count register | 105 | /// VS loop count register (Multiplied by 16) |
| 106 | static const X64Reg LOOPCOUNT_REG = R12; | 106 | static const X64Reg LOOPCOUNT_REG = R12; |
| 107 | /// Current VS loop iteration number (we could probably use LOOPCOUNT_REG, but this quicker) | 107 | /// Current VS loop iteration number (we could probably use LOOPCOUNT_REG, but this quicker) |
| 108 | static const X64Reg LOOPCOUNT = RSI; | 108 | static const X64Reg LOOPCOUNT = RSI; |
| 109 | /// Number to increment LOOPCOUNT_REG by on each loop iteration | 109 | /// Number to increment LOOPCOUNT_REG by on each loop iteration (Multiplied by 16) |
| 110 | static const X64Reg LOOPINC = RDI; | 110 | static const X64Reg LOOPINC = RDI; |
| 111 | /// Result of the previous CMP instruction for the X-component comparison | 111 | /// Result of the previous CMP instruction for the X-component comparison |
| 112 | static const X64Reg COND0 = R13; | 112 | static const X64Reg COND0 = R13; |
| @@ -491,7 +491,7 @@ void JitShader::Compile_FLR(Instruction instr) { | |||
| 491 | if (Common::GetCPUCaps().sse4_1) { | 491 | if (Common::GetCPUCaps().sse4_1) { |
| 492 | ROUNDFLOORPS(SRC1, R(SRC1)); | 492 | ROUNDFLOORPS(SRC1, R(SRC1)); |
| 493 | } else { | 493 | } else { |
| 494 | CVTPS2DQ(SRC1, R(SRC1)); | 494 | CVTTPS2DQ(SRC1, R(SRC1)); |
| 495 | CVTDQ2PS(SRC1, R(SRC1)); | 495 | CVTDQ2PS(SRC1, R(SRC1)); |
| 496 | } | 496 | } |
| 497 | 497 | ||
| @@ -718,15 +718,18 @@ void JitShader::Compile_LOOP(Instruction instr) { | |||
| 718 | 718 | ||
| 719 | looping = true; | 719 | looping = true; |
| 720 | 720 | ||
| 721 | // This decodes the fields from the integer uniform at index instr.flow_control.int_uniform_id. | ||
| 722 | // The Y (LOOPCOUNT_REG) and Z (LOOPINC) component are kept multiplied by 16 (Left shifted by | ||
| 723 | // 4 bits) to be used as an offset into the 16-byte vector registers later | ||
| 721 | int offset = | 724 | int offset = |
| 722 | ShaderSetup::UniformOffset(RegisterType::IntUniform, instr.flow_control.int_uniform_id); | 725 | ShaderSetup::UniformOffset(RegisterType::IntUniform, instr.flow_control.int_uniform_id); |
| 723 | MOV(32, R(LOOPCOUNT), MDisp(SETUP, offset)); | 726 | MOV(32, R(LOOPCOUNT), MDisp(SETUP, offset)); |
| 724 | MOV(32, R(LOOPCOUNT_REG), R(LOOPCOUNT)); | 727 | MOV(32, R(LOOPCOUNT_REG), R(LOOPCOUNT)); |
| 725 | SHR(32, R(LOOPCOUNT_REG), Imm8(8)); | 728 | SHR(32, R(LOOPCOUNT_REG), Imm8(4)); |
| 726 | AND(32, R(LOOPCOUNT_REG), Imm32(0xff)); // Y-component is the start | 729 | AND(32, R(LOOPCOUNT_REG), Imm32(0xFF0)); // Y-component is the start |
| 727 | MOV(32, R(LOOPINC), R(LOOPCOUNT)); | 730 | MOV(32, R(LOOPINC), R(LOOPCOUNT)); |
| 728 | SHR(32, R(LOOPINC), Imm8(16)); | 731 | SHR(32, R(LOOPINC), Imm8(12)); |
| 729 | MOVZX(32, 8, LOOPINC, R(LOOPINC)); // Z-component is the incrementer | 732 | AND(32, R(LOOPINC), Imm32(0xFF0)); // Z-component is the incrementer |
| 730 | MOVZX(32, 8, LOOPCOUNT, R(LOOPCOUNT)); // X-component is iteration count | 733 | MOVZX(32, 8, LOOPCOUNT, R(LOOPCOUNT)); // X-component is iteration count |
| 731 | ADD(32, R(LOOPCOUNT), Imm8(1)); // Iteration count is X-component + 1 | 734 | ADD(32, R(LOOPCOUNT), Imm8(1)); // Iteration count is X-component + 1 |
| 732 | 735 | ||