summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/gsp_gpu.cpp2
-rw-r--r--src/video_core/pica.h2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp13
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp30
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h3
-rw-r--r--src/video_core/shader/shader_jit_x64.cpp17
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
46struct Regs { 46struct 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
181bool RasterizerCacheOpenGL::TryBlitSurfaces(CachedSurface* src_surface, 178bool 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
103static const X64Reg ADDROFFS_REG_0 = R10; 103static const X64Reg ADDROFFS_REG_0 = R10;
104static const X64Reg ADDROFFS_REG_1 = R11; 104static const X64Reg ADDROFFS_REG_1 = R11;
105/// VS loop count register 105/// VS loop count register (Multiplied by 16)
106static const X64Reg LOOPCOUNT_REG = R12; 106static 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)
108static const X64Reg LOOPCOUNT = RSI; 108static 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)
110static const X64Reg LOOPINC = RDI; 110static 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
112static const X64Reg COND0 = R13; 112static 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