#pragma once #include "runtime/gs/gs_backend.h" #include "runtime/gs/gs_texture_page_cache.h" #include #include #include class GSCpuBackend final : public GSRasterBackend { public: GSCpuBackend(); void Initialize(uint8_t *vram, uint32_t vramSize) override; void Reset() override; void Submit(const GSPrimitiveBatch &batch) override; void LoadClut(const GSTex0Reg &tex0, const GSTexClutReg &texclut) override; void BeginTransfer(const GSTransferCommand &command) override; void UploadImage(const uint8_t *data, uint32_t sizeBytes) override; void Flush() override; void TextureFlush() override; void Sync(GSSyncReason reason) override; PresentationFrame Present(const GSPresentationRequest &request) override; bool ClearFramebuffer(const GSContext &context, uint32_t rgba) override; uint32_t ConsumeLocalToHostBytes(uint8_t *dst, uint32_t maxBytes) override; uint32_t ReadVram(uint32_t psm, uint32_t base, uint32_t bw, uint32_t x, uint32_t y) const override; void WriteVram(uint32_t psm, uint32_t base, uint32_t bw, uint32_t x, uint32_t y, uint32_t value) override; void SnapshotVram(std::vector &out) const override; GSTransferSnapshot GetTransferSnapshot() const override; private: void ResetUnlocked(); void LoadClutUnlocked(const GSTex0Reg &tex0, const GSTexClutReg &texclut); uint32_t ReadVramUnlocked(uint32_t psm, uint32_t base, uint32_t bw, uint32_t x, uint32_t y) const; uint32_t ReadTextureVramUnlocked(uint32_t psm, uint32_t base, uint32_t bw, uint32_t x, uint32_t y); void WriteVramUnlocked(uint32_t psm, uint32_t base, uint32_t bw, uint32_t x, uint32_t y, uint32_t value); void DrawPrimitive(const GSPrimitiveBatch &batch); void DrawSprite(const GSPrimitiveBatch &batch); void DrawTriangle(const GSPrimitiveBatch &batch); void DrawLine(const GSPrimitiveBatch &batch); void WritePixel(const GSDrawState &state, int x, int y, int z, uint8_t r, uint8_t g, uint8_t b, uint8_t a, uint8_t fog); uint32_t SampleTexture(const GSDrawState &state, float s, float t, float q, uint16_t u, uint16_t v); uint32_t LookupCLUT(const GSDrawState &state, uint8_t index, uint8_t cpsm, uint8_t csm, uint8_t csa, uint8_t sourcePsm); void PerformLocalToLocalTransfer(); void PerformLocalToHostTransfer(); PresentationFrame PresentFromLocalMemory(const GSPresentationRequest &request); bool CopyFrameToHostRgba(const GSFrameReg &frame, uint32_t width, uint32_t height, std::vector &outPixels, bool preserveAlpha, bool useLocalMemoryLayout, bool frameBaseIsPages, uint32_t sourceOriginX, uint32_t sourceOriginY) const; using WriteVramFunc = void (*)(uint8_t *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); using ReadVramFunc = uint32_t (*)(uint8_t *, uint32_t, uint32_t, uint32_t, uint32_t); static constexpr size_t kPsmHandlerCount = 1u << 6u; mutable std::mutex m_mutex; uint8_t *m_vram = nullptr; uint32_t m_vramSize = 0; std::array m_readVramFuncs{}; std::array m_writeVramFuncs{}; std::array m_clut{}; std::array m_clutCbp{}; GSMem::TexturePageCache m_texturePageCache; GSTransferCommand m_transfer{}; GSTransferSnapshot m_transferState{}; std::vector m_localToHostBuffer; size_t m_localToHostReadPos = 0; };