void Sync() { uint32 segment_current = m_offset / m_seg_size; uint32 segment_next = (m_offset + m_size) / m_seg_size; if (segment_current != segment_next) { if (segment_next >= countof(m_fence)) { segment_next = 0; } // Align current transfer on the start of the segment m_offset = m_seg_size * segment_next; // protect the left segment m_fence[segment_current] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); // Check next segment is free if (m_fence[segment_next]) { GLenum status = glClientWaitSync(m_fence[segment_next], GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); // Potentially it doesn't work on AMD driver which might always return GL_CONDITION_SATISFIED if (status != GL_ALREADY_SIGNALED) { GL_PERF("GL_PIXEL_UNPACK_BUFFER: Sync Sync (%x)! Buffer too small ?", status); } glDeleteSync(m_fence[segment_next]); m_fence[segment_next] = 0; } } }
EXPORT_C GSinitReadFIFO2(uint8* mem, uint32 size) { GL_PERF("Init Read FIFO2"); try { s_gs->InitReadFIFO(mem, size); } catch (GSDXRecoverableError) { } }
EXPORT_C GSinitReadFIFO(uint8* mem) { GL_PERF("Init Read FIFO1"); try { s_gs->InitReadFIFO(mem, 1); } catch (GSDXRecoverableError) { } }
EXPORT_C GSinitReadFIFO2(uint8* mem, uint32 size) { GL_PERF("Init Read FIFO2"); try { s_gs->InitReadFIFO(mem, size); } catch (GSDXRecoverableError) { } catch (const std::bad_alloc&) { fprintf(stderr, "GSdx: Memory allocation error\n"); } }
void GSTextureCacheOGL::Read(Target* t, const GSVector4i& r) { if (!t->m_dirty.empty() || r.width() == 0 || r.height() == 0) return; const GIFRegTEX0& TEX0 = t->m_TEX0; GLuint fmt; int ps_shader; switch (TEX0.PSM) { case PSM_PSMCT32: case PSM_PSMCT24: fmt = GL_RGBA8; ps_shader = ShaderConvert_COPY; break; case PSM_PSMCT16: case PSM_PSMCT16S: fmt = GL_R16UI; ps_shader = ShaderConvert_RGBA8_TO_16_BITS; break; case PSM_PSMZ32: fmt = GL_R32UI; ps_shader = ShaderConvert_FLOAT32_TO_32_BITS; break; case PSM_PSMZ24: fmt = GL_R32UI; ps_shader = ShaderConvert_FLOAT32_TO_32_BITS; break; case PSM_PSMZ16: case PSM_PSMZ16S: fmt = GL_R16UI; ps_shader = ShaderConvert_FLOAT32_TO_32_BITS; break; default: return; } // Yes lots of logging, but I'm not confident with this code GL_PUSH("Texture Cache Read. Format(0x%x)", TEX0.PSM); GL_PERF("TC: Read Back Target: %d (0x%x)[fmt: 0x%x]. Size %dx%d", t->m_texture->GetID(), TEX0.TBP0, TEX0.PSM, r.width(), r.height()); GSVector4 src = GSVector4(r) * GSVector4(t->m_texture->GetScale()).xyxy() / GSVector4(t->m_texture->GetSize()).xyxy(); if(GSTexture* offscreen = m_renderer->m_dev->CopyOffscreen(t->m_texture, src, r.width(), r.height(), fmt, ps_shader)) { GSTexture::GSMap m; GSVector4i r_offscreen(0, 0, r.width(), r.height()); if(offscreen->Map(m, &r_offscreen)) { // TODO: block level write GSOffset* off = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM); switch(TEX0.PSM) { case PSM_PSMCT32: m_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r); break; case PSM_PSMCT24: m_renderer->m_mem.WritePixel24(m.bits, m.pitch, off, r); break; case PSM_PSMCT16: case PSM_PSMCT16S: m_renderer->m_mem.WritePixel16(m.bits, m.pitch, off, r); break; case PSM_PSMZ32: m_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r); break; case PSM_PSMZ24: m_renderer->m_mem.WritePixel24(m.bits, m.pitch, off, r); break; case PSM_PSMZ16: case PSM_PSMZ16S: m_renderer->m_mem.WritePixel16(m.bits, m.pitch, off, r); break; default: ASSERT(0); } offscreen->Unmap(); } // FIXME invalidate data m_renderer->m_dev->Recycle(offscreen); } }