diff --git a/src/xenia/gpu/gl4/blitter.cc b/src/xenia/gpu/gl4/blitter.cc index e528c8952..25af6446e 100644 --- a/src/xenia/gpu/gl4/blitter.cc +++ b/src/xenia/gpu/gl4/blitter.cc @@ -50,7 +50,7 @@ struct VertexData { \n\ }; \n\ "; const std::string vs_source = header + - "\n\ + "\n\ layout(location = 0) uniform vec4 src_uv_params; \n\ out gl_PerVertex { \n\ vec4 gl_Position; \n\ @@ -77,13 +77,12 @@ void main() { \n\ } \n\ "; const std::string depth_fs_source = header + - "\n\ + "\n\ layout(location = 1) uniform sampler2D src_texture; \n\ layout(location = 0) in VertexData vtx; \n\ layout(location = 0) out vec4 oC; \n\ void main() { \n\ - vec4 c = texture(src_texture, vtx.uv); \n\ - gl_FragDepth = c.r; \n\ + gl_FragDepth = texture(src_texture, vtx.uv).r; \n\ } \n\ "; diff --git a/src/xenia/gpu/gl4/command_processor.cc b/src/xenia/gpu/gl4/command_processor.cc index 28565095f..d458db9d8 100644 --- a/src/xenia/gpu/gl4/command_processor.cc +++ b/src/xenia/gpu/gl4/command_processor.cc @@ -1712,6 +1712,8 @@ CommandProcessor::UpdateStatus CommandProcessor::UpdateRenderTargets() { // TODO(benvanik): can we do this all named? // TODO(benvanik): do we want this on READ too? glBindFramebuffer(GL_DRAW_FRAMEBUFFER, cached_framebuffer->framebuffer); + + glViewport(0, 0, 2560, 2560); } return UpdateStatus::kMismatch; @@ -1840,10 +1842,6 @@ CommandProcessor::UpdateStatus CommandProcessor::UpdateViewportState() { auto& state_regs = update_viewport_state_regs_; bool dirty = false; - dirty |= SetShadowRegister(state_regs.pa_sc_window_scissor_tl, - XE_GPU_REG_PA_SC_WINDOW_SCISSOR_TL); - dirty |= SetShadowRegister(state_regs.pa_sc_window_scissor_br, - XE_GPU_REG_PA_SC_WINDOW_SCISSOR_BR); // dirty |= SetShadowRegister(state_regs.pa_cl_clip_cntl, // XE_GPU_REG_PA_CL_CLIP_CNTL); if (!dirty) { @@ -1852,11 +1850,6 @@ CommandProcessor::UpdateStatus CommandProcessor::UpdateViewportState() { draw_batcher_.Flush(DrawBatcher::FlushMode::kStateChange); - // TODO(benvanik): better scissor rect? - glViewport( - 0, 0, std::min(2560u, state_regs.pa_sc_window_scissor_br & 0x7FFF), - std::min(2560u, (state_regs.pa_sc_window_scissor_br >> 16) & 0x7FFF)); - // Clipping. // https://github.com/freedreno/amd-gpu/blob/master/include/reg/yamato/14/yamato_genenum.h#L1587 // bool clip_enabled = ((state_regs.pa_cl_clip_cntl >> 17) & 0x1) == 0; @@ -2493,7 +2486,7 @@ bool CommandProcessor::IssueCopy() { // but I can't seem to find something similar. // Maybe scissor rect/window offset? uint32_t x = 0; - uint32_t y = 0; + uint32_t y = 2560 - copy_dest_height; uint32_t w = copy_dest_pitch; uint32_t h = copy_dest_height; diff --git a/src/xenia/gpu/gl4/command_processor.h b/src/xenia/gpu/gl4/command_processor.h index d9e74e8bd..0b0e54f08 100644 --- a/src/xenia/gpu/gl4/command_processor.h +++ b/src/xenia/gpu/gl4/command_processor.h @@ -298,8 +298,6 @@ class CommandProcessor { void Reset() { std::memset(this, 0, sizeof(*this)); } } update_render_targets_regs_; struct UpdateViewportStateRegisters { - uint32_t pa_sc_window_scissor_tl; - uint32_t pa_sc_window_scissor_br; uint32_t pa_cl_clip_cntl; UpdateViewportStateRegisters() { Reset(); } diff --git a/src/xenia/gpu/gl4/gl4_graphics_system.cc b/src/xenia/gpu/gl4/gl4_graphics_system.cc index 42af232de..f311668e6 100644 --- a/src/xenia/gpu/gl4/gl4_graphics_system.cc +++ b/src/xenia/gpu/gl4/gl4_graphics_system.cc @@ -258,6 +258,10 @@ void GL4GraphicsSystem::SwapHandler(const SwapParameters& swap_params) { // Swap requested. Synchronously post a request to the loop so that // we do the swap in the right thread. control_->SynchronousRepaint([&]() { + if (!swap_params.framebuffer_texture) { + // no-op. + return; + } control_->context()->blitter()->BlitTexture2D( swap_params.framebuffer_texture, swap_params.x, swap_params.y, swap_params.width, swap_params.height, 0, 0, control_->width(), diff --git a/src/xenia/gpu/gl4/gl4_shader.cc b/src/xenia/gpu/gl4/gl4_shader.cc index 9bc14e2ad..14ff61438 100644 --- a/src/xenia/gpu/gl4/gl4_shader.cc +++ b/src/xenia/gpu/gl4/gl4_shader.cc @@ -185,39 +185,40 @@ bool GL4Shader::PrepareVertexShader( } std::string apply_transform = - "vec4 applyTransform(const in StateData state, vec4 pos) {\n" + "vec4 applyTransform(const in StateData state, vec4 Pclip) {\n" " // Clip->NDC with perspective divide.\n" " // We do this here because it's programmable on the 360.\n" - " float w = pos.w;\n" - " if (state.vtx_fmt.w == 0.0) {\n" + " if (state.vtx_fmt.w != 0.0) {\n" " // w is not 1/W0. Common case.\n" - " w = 1.0 / w;\n" + " Pclip.w = 1.0 / Pclip.w;\n" " }\n" - " if (state.vtx_fmt.x != 0.0) {\n" + " vec3 Pndc = Pclip.xyz;\n" + " if (state.vtx_fmt.x == 0.0) {\n" " // Need to multiply by 1/W0.\n" - " pos.xy *= w;\n" + " Pndc.xy *= Pclip.w;\n" " }\n" - " if (state.vtx_fmt.z != 0.0) {\n" + " if (state.vtx_fmt.z == 0.0) {\n" " // Need to multiply by 1/W0.\n" - " pos.z *= w;\n" + " Pndc.z *= Pclip.w;\n" " }\n" - " pos.w = w;\n" " // Perform clipping, lest we get weird geometry.\n" // TODO(benvanik): is this right? dxclip mode may change this? - //" if (pos.z < gl_DepthRange.near || pos.z > gl_DepthRange.far) {\n" - //" // Clipped! w=0 will kill it in the hardware persp divide.\n" - //" pos.w = 0.0;\n" - //" }\n" - " // NDC transform.\n" - " pos.xyz = pos.xyz * state.viewport_scale.xyz + \n" + " Pclip.w = 1.0;\n" + " if (Pndc.z < gl_DepthRange.near || Pndc.z > gl_DepthRange.far) {\n" + " // Clipped! w=0 will kill it in the hardware persp divide.\n" + " Pclip.w = 0.0;\n" + " }\n" + " vec3 Pwnd = Pndc.xyz * state.viewport_scale.xyz + \n" " state.viewport_offset.xyz;\n" - " // NDC->Window with viewport.\n" - " pos.xy = pos.xy * state.window_offset.zw + state.window_offset.xy;\n" - " // Put back in to ndc for glViewport to then take it back out again.\n" - " // Note the 1px scaling adjustment to fully fill the window.\n" - " pos.xy = pos.xy / ((state.window_scissor.zw - 1.0) /\n" - " vec2(2.0, -2.0)) + vec2(-1.0, 1.0);\n" - " return pos;\n" + " // 1px padding required for pixel offset issue.\n" + " Pwnd.xy += 1.0;\n" + " vec3 Pwnd2 = vec3(Pwnd.xy * state.window_offset.zw + \n" + " state.window_offset.xy, Pwnd.z);\n" + " Pwnd2.y = 2560.0 - Pwnd2.y;\n" + " vec3 fb_offset = vec3(2560.0 / 2.0, 2560.0 / 2.0, 0.0);\n" + " vec3 fb_scale = vec3(2560.0 / 2.0, 2560.0 / 2.0, 1.0);\n" + " vec3 Pndc2 = (Pwnd2.xyz - fb_offset.xyz) / fb_scale.xyz;\n" + " return vec4(Pndc2.xy, Pndc2.z, Pclip.w);\n" "}\n"; std::string source = GetHeader() + apply_transform + @@ -265,15 +266,24 @@ bool GL4Shader::PreparePixelShader( } has_prepared_ = true; - std::string source = GetHeader() + - "layout(location = 0) flat in uint draw_id;\n" - "layout(location = 1) in VertexData vtx;\n" - "layout(location = 0) out vec4 oC[4];\n" - "void processFragment(const in StateData state);\n" - "void main() {\n" + - " const StateData state = states[draw_id];\n" - " processFragment(state);\n" - "}\n"; + std::string source = + GetHeader() + + "layout(origin_upper_left) in vec4 gl_FragCoord;\n" + "layout(location = 0) flat in uint draw_id;\n" + "layout(location = 1) in VertexData vtx;\n" + "layout(location = 0) out vec4 oC[4];\n" + "void processFragment(const in StateData state);\n" + "void main() {\n" + + " const StateData state = states[draw_id];\n" + " // Custom scissoring. Doing it here avoids the need for glScissor.\n" + " if (gl_FragCoord.x < state.window_scissor.x ||\n" + " gl_FragCoord.x > state.window_scissor.z ||\n" + " gl_FragCoord.y < state.window_scissor.y ||\n" + " gl_FragCoord.y > state.window_scissor.w) {\n" + " discard;\n" + " }\n" + " processFragment(state);\n" + "}\n"; std::string translated_source = shader_translator_.TranslatePixelShader(this, program_cntl); @@ -358,8 +368,8 @@ bool GL4Shader::CompileProgram(std::string source) { char* search_start = reinterpret_cast(translated_binary_.data()); while (true) { auto p = reinterpret_cast( - memchr(translated_binary_.data() + search_offset, '!', - translated_binary_.size() - search_offset)); + memchr(translated_binary_.data() + search_offset, '!', + translated_binary_.size() - search_offset)); if (!p) { break; }