Merge pull request #1132 from vlj/rsx

Rsx: Some interface changes
This commit is contained in:
Hykem 2015-07-04 12:02:45 +01:00
commit a114dbcd76
7 changed files with 123 additions and 42 deletions

View File

@ -765,6 +765,14 @@ size_t get_x64_access_size(x64_context* context, x64_op_t op, x64_reg_t reg, siz
return d_size;
}
/**
* Callback that can be customised by GSRender backends to track memory access.
* Backends can protect memory pages and get this callback called when an access
* violation is met.
* Should return true if the backend handles the access violation.
*/
std::function<bool(u32 addr)> gfxHandler = [](u32) { return false; };
bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
{
auto code = (const u8*)RIP(context);
@ -774,6 +782,9 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
size_t d_size;
size_t i_size;
if (gfxHandler(addr))
return true;
// decode single x64 instruction that causes memory access
decode_x64_reg_op(code, op, reg, d_size, i_size);

View File

@ -425,10 +425,10 @@ namespace vm
DWORD old;
auto protection = f2 & page_writable ? PAGE_READWRITE : (f2 & page_readable ? PAGE_READONLY : PAGE_NOACCESS);
if (!VirtualProtect(real_addr, size, protection, &old))
if (!VirtualProtect(real_addr, 4096, protection, &old))
#else
auto protection = f2 & page_writable ? PROT_WRITE | PROT_READ : (f2 & page_readable ? PROT_READ : PROT_NONE);
if (mprotect(real_addr, size, protection))
if (mprotect(real_addr, 4096, protection))
#endif
{
throw fmt::format("vm::page_protect(addr=0x%x, size=0x%x, flags_test=0x%x, flags_set=0x%x, flags_clear=0x%x) failed (API)", addr, size, flags_test, flags_set, flags_clear);

View File

@ -1599,7 +1599,7 @@ void GLGSRender::InitDrawBuffers()
}
}
void GLGSRender::ExecCMD(u32 cmd)
void GLGSRender::Clear(u32 cmd)
{
assert(cmd == NV4097_CLEAR_SURFACE);
@ -1653,7 +1653,7 @@ void GLGSRender::ExecCMD(u32 cmd)
WriteBuffers();
}
void GLGSRender::ExecCMD()
void GLGSRender::Draw()
{
//return;
if (!LoadProgram())
@ -1966,9 +1966,9 @@ void GLGSRender::ExecCMD()
m_vao.Bind();
if (m_indexed_array.m_count)
{
LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1);
}
else
LoadVertexData(m_draw_array_first, m_draw_array_count);
if (m_indexed_array.m_count || m_draw_array_count)
{
@ -2143,6 +2143,21 @@ void GLGSRender::Flip()
}
void GLGSRender::semaphorePGRAPHTextureReadRelease(u32 offset, u32 value)
{
vm::write32(m_label_addr + offset, value);
}
void GLGSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value)
{
vm::write32(m_label_addr + offset, value);
}
void GLGSRender::semaphorePFIFOAcquire(u32 offset, u32 value)
{
}
u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, u32 log2_depth)
{
u32 offset = 0;

View File

@ -194,7 +194,11 @@ protected:
virtual void OnInitThread();
virtual void OnExitThread();
virtual void OnReset();
virtual void ExecCMD(u32 cmd);
virtual void ExecCMD();
virtual void Clear(u32 cmd) override;
virtual void Draw() override;
virtual void Flip();
virtual void semaphorePGRAPHTextureReadRelease(u32 offset, u32 value) override;
virtual void semaphorePGRAPHBackendRelease(u32 offset, u32 value) override;
virtual void semaphorePFIFOAcquire(u32 offset, u32 value) override;
};

View File

@ -31,11 +31,11 @@ private:
{
}
virtual void ExecCMD(u32 cmd)
virtual void Clear(u32 cmd) override
{
}
virtual void ExecCMD()
virtual void Draw() override
{
}
@ -46,4 +46,16 @@ private:
virtual void Close()
{
}
virtual void semaphorePGRAPHTextureReadRelease(u32 offset, u32 value) override
{
}
virtual void semaphorePGRAPHBackendRelease(u32 offset, u32 value) override
{
}
virtual void semaphorePFIFOAcquire(u32 offset, u32 value) override
{
}
};

View File

@ -201,43 +201,40 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
}
case NV4097_SET_SEMAPHORE_OFFSET:
{
m_PGRAPH_semaphore_offset = ARGS(0);
break;
}
case NV406E_SEMAPHORE_OFFSET:
{
m_set_semaphore_offset = true;
m_semaphore_offset = ARGS(0);
m_PFIFO_semaphore_offset = ARGS(0);
break;
}
case NV406E_SEMAPHORE_ACQUIRE:
{
if (ARGS(0))
{
LOG_WARNING(RSX, "TODO: NV406E_SEMAPHORE_ACQUIRE: 0x%x", ARGS(0));
}
semaphorePFIFOAcquire(m_PFIFO_semaphore_offset, ARGS(0));
break;
}
case NV406E_SEMAPHORE_RELEASE:
{
m_PFIFO_semaphore_release_value = ARGS(0);
break;
}
case NV4097_TEXTURE_READ_SEMAPHORE_RELEASE:
{
if (m_set_semaphore_offset)
{
m_set_semaphore_offset = false;
vm::write32(m_label_addr + m_semaphore_offset, ARGS(0));
}
semaphorePGRAPHTextureReadRelease(m_PGRAPH_semaphore_offset, ARGS(0));
break;
}
case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE:
{
if (m_set_semaphore_offset)
{
m_set_semaphore_offset = false;
u32 value = ARGS(0);
value = (value & 0xff00ff00) | ((value & 0xff) << 16) | ((value >> 16) & 0xff);
vm::write32(m_label_addr + m_semaphore_offset, value);
}
u32 value = ARGS(0);
value = (value & 0xff00ff00) | ((value & 0xff) << 16) | ((value >> 16) & 0xff);
semaphorePGRAPHBackendRelease(m_PGRAPH_semaphore_offset, value);
break;
}
@ -850,7 +847,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
if (a0 & 0x80) m_clear_surface_color_a = m_clear_color_a;
m_clear_surface_mask = a0;
ExecCMD(NV4097_CLEAR_SURFACE);
Clear(NV4097_CLEAR_SURFACE);
break;
}
@ -910,8 +907,6 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
//LOG_WARNING(RSX, "NV4097_DRAW_ARRAYS: %d - %d", first, _count);
LoadVertexData(first, _count);
if (first < m_draw_array_first)
{
m_draw_array_first = first;
@ -942,10 +937,10 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
switch (m_indexed_array.m_type)
{
case 0:
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
m_indexed_array.m_data.resize(pos + 4 * _count);
break;
case 1:
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
m_indexed_array.m_data.resize(pos + 2 * _count);
break;
}
@ -955,12 +950,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
u32 index;
switch(m_indexed_array.m_type)
{
case 0:
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
index = vm::read32(m_indexed_array.m_addr + i * 4);
*(u32*)&m_indexed_array.m_data[i * 4] = index;
break;
case 1:
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
index = vm::read16(m_indexed_array.m_addr + i * 2);
*(u16*)&m_indexed_array.m_data[i * 2] = index;
break;
@ -1177,6 +1172,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
break;
}
case NV4097_SET_NO_PARANOID_TEXTURE_FETCHES:
{
// Nothing to do here
break;
}
case NV4097_INVALIDATE_VERTEX_CACHE_FILE:
{
// Nothing to do here
@ -2415,7 +2416,7 @@ void RSXThread::Begin(u32 draw_mode)
void RSXThread::End()
{
ExecCMD();
Draw();
for (auto &vdata : m_vertex_data)
{

View File

@ -343,8 +343,11 @@ public:
s32 m_color_conv_dtdy;
// Semaphore
bool m_set_semaphore_offset;
u32 m_semaphore_offset;
// PGRAPH
u32 m_PGRAPH_semaphore_offset;
//PFIFO
u32 m_PFIFO_semaphore_offset;
u32 m_PFIFO_semaphore_release_value;
// Fog
bool m_set_fog_mode;
@ -597,7 +600,6 @@ protected:
m_set_line_width = false;
m_set_line_smooth = false;
m_set_shade_mode = false;
m_set_semaphore_offset = false;
m_set_fog_mode = false;
m_set_fog_params = false;
m_set_clip_plane = false;
@ -644,10 +646,46 @@ protected:
virtual void OnInitThread() = 0;
virtual void OnExitThread() = 0;
virtual void OnReset() = 0;
virtual void ExecCMD() = 0;
virtual void ExecCMD(u32 cmd) = 0;
/**
* This member is called when the backend is expected to render a draw call, either
* indexed or not.
*/
virtual void Draw() = 0;
/**
* This member is called when the backend is expected to clear a target surface.
*/
virtual void Clear(u32 cmd) = 0;
/**
* This member is called when the backend is expected to present a target surface in
* either local or main memory.
*/
virtual void Flip() = 0;
/**
* This member is called when RSXThread parse a TEXTURE_READ_SEMAPHORE_RELEASE
* command.
* Backend is expected to write value at offset when current draw textures aren't
* needed anymore by the GPU and can be modified.
*/
virtual void semaphorePGRAPHTextureReadRelease(u32 offset, u32 value) = 0;
/**
* This member is called when RSXThread parse a BACK_END_WRITE_SEMAPHORE_RELEASE
* command.
* Backend is expected to write value at offset when current draw call has completed
* and render surface can be used.
*/
virtual void semaphorePGRAPHBackendRelease(u32 offset, u32 value) = 0;
/**
* This member is called when RSXThread parse a SEMAPHORE_ACQUIRE command.
* Backend and associated GPU is expected to wait that memory at offset is the same
* as value. In particular buffer/texture buffers value can change while backend is
* waiting.
*/
virtual void semaphorePFIFOAcquire(u32 offset, u32 value) = 0;
void LoadVertexData(u32 first, u32 count)
{
for (u32 i = 0; i < m_vertex_count; ++i)