| 2717 | } |
| 2718 | |
| 2719 | void GSState::CheckWriteOverlap(bool req_write, bool req_read) |
| 2720 | { |
| 2721 | const int w = m_env.TRXREG.RRW; |
| 2722 | const int h = m_env.TRXREG.RRH; |
| 2723 | const GIFRegBITBLTBUF& blit = m_env.BITBLTBUF; |
| 2724 | |
| 2725 | const GSVector4i write_rect = GSVector4i(m_env.TRXPOS.DSAX, m_env.TRXPOS.DSAY, m_env.TRXPOS.DSAX + w, m_env.TRXPOS.DSAY + h); |
| 2726 | const u32 write_start_bp = GSLocalMemory::GetStartBlockAddress(blit.DBP, blit.DBW, blit.DPSM, write_rect); |
| 2727 | const u32 write_end_bp = ((GSLocalMemory::GetEndBlockAddress(blit.DBP, blit.DBW, blit.DPSM, write_rect) + 1) + (GS_BLOCKS_PER_PAGE - 1)) & ~(GS_BLOCKS_PER_PAGE - 1); |
| 2728 | |
| 2729 | for (int i = 0; i < m_used_buffers_idx; i++) |
| 2730 | { |
| 2731 | GSIndexBuff* cur_index_buff = &m_index_buffers[i]; |
| 2732 | GSVertexBuff* cur_vertex_buff = &m_vertex_buffers[i]; |
| 2733 | const GSDrawingContext& prev_ctx = m_env_buffers[i].m_env.CTXT[m_env_buffers[i].m_backed_up_ctx]; |
| 2734 | const GSDrawingEnvironment& prev_env = m_env_buffers[i].m_env; |
| 2735 | GSVector4i tex_rect = prev_env.PRIM.TME ? GetTEX0Rect(prev_ctx) : GSVector4i::zero(); |
| 2736 | |
| 2737 | if (cur_index_buff->tail > 0) |
| 2738 | { |
| 2739 | // Only flush on a NEW transfer if a pending one is using the same address or overlap. |
| 2740 | // Check Fast & Furious (Hardare mode) and Assault Suits Valken (either renderer) and Tomb Raider - Angel of Darkness menu (TBP != DBP but overlaps). |
| 2741 | // Cartoon Network overwrites its own Z buffer in the middle of a draw. |
| 2742 | // Alias wraps its transfers, so be careful |
| 2743 | const GSVector4i read_rect = GSVector4i(m_env.TRXPOS.SSAX, m_env.TRXPOS.SSAY, m_env.TRXPOS.SSAX + w, m_env.TRXPOS.SSAY + h); |
| 2744 | |
| 2745 | if (req_write && prev_env.PRIM.TME) |
| 2746 | { |
| 2747 | // Tex rect could be invalid showing 1024x1024 when it isn't. If the frame is only 1 page wide, it's either a big strip or a single page draw. |
| 2748 | // This large texture causes misdetection of overlapping writes, causing our heuristics in the hardware renderer for future draws to be missing. |
| 2749 | // Either way if we check the queued up coordinates, it should give us a fair idea. (Cabela's Trophy Bucks) |
| 2750 | if (prev_ctx.FRAME.FBW == 1 && static_cast<u32>(tex_rect.width()) > (prev_ctx.TEX0.TBW * 64)) |
| 2751 | { |
| 2752 | GSVector4i tex_draw_rect = GSVector4i::zero(); |
| 2753 | for (u32 i = 0; i < cur_index_buff->tail; i++) |
| 2754 | { |
| 2755 | const GSVertex* v = &cur_vertex_buff->buff[cur_index_buff->buff[i]]; |
| 2756 | GSVector2i tex_coord; |
| 2757 | if (PRIM->FST) |
| 2758 | { |
| 2759 | tex_coord.x = v->U >> 4; |
| 2760 | tex_coord.y = v->V >> 4; |
| 2761 | } |
| 2762 | else |
| 2763 | { |
| 2764 | const float s = std::min((v->ST.S / v->RGBAQ.Q), 1.0f); |
| 2765 | const float t = std::min((v->ST.T / v->RGBAQ.Q), 1.0f); |
| 2766 | |
| 2767 | tex_coord.x = static_cast<int>(std::round((1 << prev_ctx.TEX0.TW) * s)); |
| 2768 | tex_coord.y = static_cast<int>(std::round((1 << prev_ctx.TEX0.TH) * t)); |
| 2769 | } |
| 2770 | |
| 2771 | if (i == 0) |
| 2772 | { |
| 2773 | tex_draw_rect.x = tex_coord.x; |
| 2774 | tex_draw_rect.y = tex_coord.y; |
| 2775 | tex_draw_rect.z = tex_coord.x; |
| 2776 | tex_draw_rect.w = tex_coord.y; |
nothing calls this directly
no test coverage detected