mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-14 01:27:00 +00:00
Implemented depth(stencil) textures reading/writing
Implemented swizzled textures reading Minor fixes
This commit is contained in:
parent
8e57cf8da8
commit
220d48a980
@ -31,21 +31,69 @@ namespace
|
||||
throw EXCEPTION("Unknow depth format");
|
||||
}
|
||||
|
||||
u32 to_gl_internal_type(rsx::vertex_base_type type, u8 size)
|
||||
gl::texture::sized_internal_format to_gl_internal_type(rsx::vertex_base_type type, u8 size)
|
||||
{
|
||||
/**
|
||||
* The buffer texture spec only allows fetches aligned to 8, 16, 32, etc...
|
||||
* This rules out most 3-component formats, except for the 32-wide RGB32F, RGB32I, RGB32UI
|
||||
*/
|
||||
const u32 vec1_types[] = { GL_R16, GL_R32F, GL_R16F, GL_R8, GL_R16I, GL_R16, GL_R8UI };
|
||||
const u32 vec2_types[] = { GL_RG16, GL_RG32F, GL_RG16F, GL_RG8, GL_RG16I, GL_RG16, GL_RG8UI };
|
||||
const u32 vec3_types[] = { GL_RGBA16, GL_RGB32F, GL_RGBA16F, GL_RGBA8, GL_RGBA16I, GL_RGBA16, GL_RGBA8UI }; //VEC3 COMPONENTS NOT SUPPORTED!
|
||||
const u32 vec4_types[] = { GL_RGBA16, GL_RGBA32F, GL_RGBA16F, GL_RGBA8, GL_RGBA16I, GL_RGBA16, GL_RGBA8UI };
|
||||
static const gl::texture::sized_internal_format vec1_types[]
|
||||
{
|
||||
gl::texture::sized_internal_format::r16,
|
||||
gl::texture::sized_internal_format::r32f,
|
||||
gl::texture::sized_internal_format::r16f,
|
||||
gl::texture::sized_internal_format::r8,
|
||||
gl::texture::sized_internal_format::r16i,
|
||||
gl::texture::sized_internal_format::r16,
|
||||
gl::texture::sized_internal_format::r8ui
|
||||
};
|
||||
|
||||
const u32* vec_selectors[] = { 0, vec1_types, vec2_types, vec3_types, vec4_types };
|
||||
static const gl::texture::sized_internal_format vec2_types[]
|
||||
{
|
||||
gl::texture::sized_internal_format::rg16,
|
||||
gl::texture::sized_internal_format::rg32f,
|
||||
gl::texture::sized_internal_format::rg16f,
|
||||
gl::texture::sized_internal_format::rg8,
|
||||
gl::texture::sized_internal_format::rg16i,
|
||||
gl::texture::sized_internal_format::rg16,
|
||||
gl::texture::sized_internal_format::rg8ui
|
||||
};
|
||||
|
||||
static const gl::texture::sized_internal_format vec3_types[] //VEC3 COMPONENTS NOT SUPPORTED!
|
||||
{
|
||||
gl::texture::sized_internal_format::rgba16,
|
||||
gl::texture::sized_internal_format::rgb32f,
|
||||
gl::texture::sized_internal_format::rgba16f,
|
||||
gl::texture::sized_internal_format::rgba8,
|
||||
gl::texture::sized_internal_format::rgba16i,
|
||||
gl::texture::sized_internal_format::rgba16,
|
||||
gl::texture::sized_internal_format::rgba8ui
|
||||
};
|
||||
|
||||
static const gl::texture::sized_internal_format vec4_types[]
|
||||
{
|
||||
gl::texture::sized_internal_format::rgba16,
|
||||
gl::texture::sized_internal_format::rgba32f,
|
||||
gl::texture::sized_internal_format::rgba16f,
|
||||
gl::texture::sized_internal_format::rgba8,
|
||||
gl::texture::sized_internal_format::rgba16i,
|
||||
gl::texture::sized_internal_format::rgba16,
|
||||
gl::texture::sized_internal_format::rgba8ui
|
||||
};
|
||||
|
||||
static const gl::texture::sized_internal_format* vec_selectors[]
|
||||
{
|
||||
nullptr,
|
||||
vec1_types,
|
||||
vec2_types,
|
||||
vec3_types,
|
||||
vec4_types
|
||||
};
|
||||
|
||||
if (type > rsx::vertex_base_type::ub256)
|
||||
{
|
||||
throw EXCEPTION("OpenGL error: unknown vertex base type 0x%X.", (u32)type);
|
||||
}
|
||||
|
||||
return vec_selectors[size][(int)type];
|
||||
}
|
||||
@ -189,9 +237,9 @@ void GLGSRender::begin()
|
||||
|
||||
if (u32 blend_mrt = rsx::method_registers[NV4097_SET_BLEND_ENABLE_MRT])
|
||||
{
|
||||
__glcheck enable(blend_mrt & 2, GL_BLEND, GL_COLOR_ATTACHMENT1);
|
||||
__glcheck enable(blend_mrt & 4, GL_BLEND, GL_COLOR_ATTACHMENT2);
|
||||
__glcheck enable(blend_mrt & 8, GL_BLEND, GL_COLOR_ATTACHMENT3);
|
||||
__glcheck enable(blend_mrt & 2, GL_BLEND, 1);
|
||||
__glcheck enable(blend_mrt & 4, GL_BLEND, 2);
|
||||
__glcheck enable(blend_mrt & 8, GL_BLEND, 3);
|
||||
}
|
||||
|
||||
if (__glcheck enable(rsx::method_registers[NV4097_SET_LOGIC_OP_ENABLE], GL_LOGIC_OP))
|
||||
@ -347,7 +395,7 @@ namespace
|
||||
case rsx::vertex_base_type::ub: return gl::buffer_pointer::type::u8;
|
||||
case rsx::vertex_base_type::s32k: return gl::buffer_pointer::type::s32;
|
||||
case rsx::vertex_base_type::cmp: return gl::buffer_pointer::type::s16; // Needs conversion
|
||||
case rsx::vertex_base_type::ub256: gl::buffer_pointer::type::u8;
|
||||
case rsx::vertex_base_type::ub256: return gl::buffer_pointer::type::u8;
|
||||
}
|
||||
throw EXCEPTION("unknow vertex type");
|
||||
}
|
||||
@ -389,7 +437,7 @@ void GLGSRender::end()
|
||||
int location;
|
||||
if (m_program->uniforms.has_location("tex" + std::to_string(i), &location))
|
||||
{
|
||||
__glcheck rsx::gl_texture::bind(m_texture_cache, i, textures[i]);
|
||||
__glcheck rsx::gl_texture::bind(m_texture_cache, textures[i]);
|
||||
__glcheck glProgramUniform1i(m_program->id(), location, i);
|
||||
}
|
||||
}
|
||||
@ -472,7 +520,7 @@ void GLGSRender::end()
|
||||
|
||||
const u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
|
||||
u32 data_size = element_size * vertex_draw_count;
|
||||
u32 gl_type = to_gl_internal_type(vertex_info.type, vertex_info.size);
|
||||
gl::texture::sized_internal_format gl_type = to_gl_internal_type(vertex_info.type, vertex_info.size);
|
||||
|
||||
auto &buffer = m_gl_attrib_buffers[index].buffer;
|
||||
auto &texture = m_gl_attrib_buffers[index].texture;
|
||||
@ -530,7 +578,7 @@ void GLGSRender::end()
|
||||
if (!enabled)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + index + rsx::limits::textures_count);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, NULL);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
glProgramUniform1i(m_program->id(), location, index + rsx::limits::textures_count);
|
||||
continue;
|
||||
}
|
||||
@ -573,16 +621,11 @@ void GLGSRender::end()
|
||||
vertex_arrays_offsets[index] = gsl::narrow<u32>(position);
|
||||
vertex_arrays_data.resize(position + size);
|
||||
|
||||
u32 gl_type = to_gl_internal_type(vertex_info.type, vertex_info.size);
|
||||
u32 data_size = element_size * vertex_draw_count;
|
||||
gl::texture::sized_internal_format gl_type = to_gl_internal_type(vertex_info.type, vertex_info.size);
|
||||
|
||||
auto& attrib_pair = m_gl_attrib_buffers[index];
|
||||
|
||||
__glcheck 0;
|
||||
|
||||
attrib_pair.buffer.data(data_size, vertex_array.data());
|
||||
|
||||
__glcheck 0;
|
||||
attrib_pair.buffer.data(vertex_array.size(), vertex_array.data());
|
||||
|
||||
//Attach buffer to texture
|
||||
attrib_pair.texture.copy_from(attrib_pair.buffer, gl_type);
|
||||
@ -601,12 +644,11 @@ void GLGSRender::end()
|
||||
case rsx::vertex_base_type::f:
|
||||
{
|
||||
const u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
|
||||
const u32 gl_type = to_gl_internal_type(vertex_info.type, vertex_info.size);
|
||||
const size_t data_size = vertex_data.size();
|
||||
gl::texture::sized_internal_format gl_type = to_gl_internal_type(vertex_info.type, vertex_info.size);
|
||||
|
||||
auto& attrib_pair = m_gl_attrib_buffers[index];
|
||||
|
||||
attrib_pair.buffer.data(data_size, vertex_data.data());
|
||||
attrib_pair.buffer.data(vertex_data.size(), vertex_data.data());
|
||||
|
||||
//Attach buffer to texture
|
||||
attrib_pair.texture.copy_from(attrib_pair.buffer, gl_type);
|
||||
@ -623,7 +665,7 @@ void GLGSRender::end()
|
||||
else
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + index + rsx::limits::textures_count);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, NULL);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
glProgramUniform1i(m_program->id(), location, index + rsx::limits::textures_count);
|
||||
continue;
|
||||
}
|
||||
@ -1080,7 +1122,7 @@ u32 surface_format_to_texture_format(rsx::surface_color_format format)
|
||||
|
||||
gl::texture_info surface_info(rsx::surface_color_format format, u32 offset, u32 location, u32 width, u32 height, u32 pitch)
|
||||
{
|
||||
gl::texture_info info;
|
||||
gl::texture_info info{};
|
||||
|
||||
info.width = width;
|
||||
info.height = height;
|
||||
@ -1089,6 +1131,8 @@ gl::texture_info surface_info(rsx::surface_color_format format, u32 offset, u32
|
||||
info.compressed_size = 0;
|
||||
info.target = gl::texture::target::texture2D;
|
||||
info.dimension = 2;
|
||||
//TODO
|
||||
info.swizzled = false;
|
||||
info.start_address = rsx::get_address(offset, location);
|
||||
|
||||
info.format = gl::get_texture_format(surface_format_to_texture_format(format));
|
||||
@ -1144,7 +1188,7 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||
u32 location = rsx::method_registers[mr_color_dma[index]];
|
||||
u32 pitch = rsx::method_registers[mr_color_pitch[index]];
|
||||
|
||||
if (!location)
|
||||
if (pitch <= 64)
|
||||
{
|
||||
cached_color_buffers[index] = nullptr;
|
||||
draw_fbo.color[index] = null_texture;
|
||||
@ -1162,14 +1206,14 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||
u32 location = rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA];
|
||||
u32 pitch = rsx::method_registers[NV4097_SET_SURFACE_PITCH_Z];
|
||||
|
||||
if (!location)
|
||||
if (pitch <= 64)
|
||||
{
|
||||
cached_depth_buffer = nullptr;
|
||||
draw_fbo.depth_stencil = null_texture;
|
||||
}
|
||||
else
|
||||
{
|
||||
gl::texture_info info;
|
||||
gl::texture_info info{};
|
||||
|
||||
info.width = m_surface.width;
|
||||
info.height = m_surface.height;
|
||||
@ -1179,6 +1223,8 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||
info.compressed_size = 0;
|
||||
info.start_address = rsx::get_address(offset, location);
|
||||
info.target = gl::texture::target::texture2D;
|
||||
//TODO
|
||||
info.swizzled = false;
|
||||
|
||||
switch (m_surface.depth_format)
|
||||
{
|
||||
@ -1203,24 +1249,24 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||
}
|
||||
|
||||
info.format.remap = { GL_ZERO, GL_ZERO, GL_ZERO, GL_ZERO };
|
||||
|
||||
cached_depth_buffer = &m_texture_cache.entry(info, skip_reading ? gl::cache_buffers::none : gl::cache_buffers::local);
|
||||
__glcheck 0;
|
||||
__glcheck cached_depth_buffer = &m_texture_cache.entry(info, skip_reading ? gl::cache_buffers::none : gl::cache_buffers::local);
|
||||
|
||||
|
||||
switch (m_surface.depth_format)
|
||||
{
|
||||
case rsx::surface_depth_format::z16:
|
||||
draw_fbo.depth = cached_depth_buffer->view();
|
||||
__glcheck draw_fbo.depth = cached_depth_buffer->view();
|
||||
break;
|
||||
|
||||
case rsx::surface_depth_format::z24s8:
|
||||
draw_fbo.depth_stencil = cached_depth_buffer->view();
|
||||
__glcheck draw_fbo.depth_stencil = cached_depth_buffer->view();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_fbo.bind();
|
||||
__glcheck draw_fbo.bind();
|
||||
|
||||
{
|
||||
auto info = rsx::get_active_color_surfaces();
|
||||
@ -1233,7 +1279,7 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||
GL_COLOR_ATTACHMENT3
|
||||
};
|
||||
|
||||
glDrawBuffers(info.second, color_buffers + info.first);
|
||||
__glcheck glDrawBuffers(info.second, color_buffers + info.first);
|
||||
}
|
||||
|
||||
set_viewport();
|
||||
@ -1323,7 +1369,7 @@ bool GLGSRender::on_access_violation(u32 address, bool is_writing)
|
||||
{
|
||||
if (auto region = m_texture_cache.find_region(address))
|
||||
{
|
||||
std::lock_guard<gl::protected_region> lock(*region);
|
||||
//std::lock_guard<gl::protected_region> lock(*region);
|
||||
|
||||
if (is_writing)
|
||||
{
|
||||
|
@ -173,6 +173,10 @@ OPENGL_PROC(PFNGLTEXTUREBUFFERRANGEEXTPROC, TextureBufferRangeEXT);
|
||||
OPENGL_PROC(PFNGLTEXSTORAGE1DPROC, TexStorage1D);
|
||||
OPENGL_PROC(PFNGLTEXSTORAGE2DPROC, TexStorage2D);
|
||||
OPENGL_PROC(PFNGLTEXSTORAGE3DPROC, TexStorage3D);
|
||||
OPENGL_PROC(PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC, CompressedTexSubImage1D);
|
||||
OPENGL_PROC(PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC, CompressedTexSubImage2D);
|
||||
OPENGL_PROC(PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC, CompressedTexSubImage3D);
|
||||
OPENGL_PROC(PFNGLCLEARTEXIMAGEPROC, ClearTexImage);
|
||||
|
||||
//ARB_Copy_Image
|
||||
OPENGL_PROC(PFNGLCOPYIMAGESUBDATAPROC, CopyImageSubData);
|
||||
|
@ -810,6 +810,7 @@ namespace gl
|
||||
r32f = GL_R32F,
|
||||
r8ui = GL_R8UI,
|
||||
r8i = GL_R8I,
|
||||
r16 = GL_R16,
|
||||
r16ui = GL_R16UI,
|
||||
r16i = GL_R16I,
|
||||
r32ui = GL_R32UI,
|
||||
@ -820,6 +821,7 @@ namespace gl
|
||||
rg32f = GL_RG32F,
|
||||
rg8ui = GL_RG8UI,
|
||||
rg8i = GL_RG8I,
|
||||
rg16 = GL_RG16,
|
||||
rg16ui = GL_RG16UI,
|
||||
rg16i = GL_RG16I,
|
||||
rg32ui = GL_RG32UI,
|
||||
@ -830,6 +832,7 @@ namespace gl
|
||||
rgb8_snorm = GL_RGB8_SNORM,
|
||||
r11f_g11f_b10f = GL_R11F_G11F_B10F,
|
||||
rgb9_e5 = GL_RGB9_E5,
|
||||
rgb16 = GL_RGB16,
|
||||
rgb16f = GL_RGB16F,
|
||||
rgb32f = GL_RGB32F,
|
||||
rgb8ui = GL_RGB8UI,
|
||||
@ -849,6 +852,7 @@ namespace gl
|
||||
rgba8ui = GL_RGBA8UI,
|
||||
rgba8i = GL_RGBA8I,
|
||||
rgb10_a2ui = GL_RGB10_A2UI,
|
||||
rgba16 = GL_RGBA16,
|
||||
rgba16ui = GL_RGBA16UI,
|
||||
rgba16i = GL_RGBA16I,
|
||||
rgba32i = GL_RGBA32I,
|
||||
@ -1203,27 +1207,27 @@ namespace gl
|
||||
__glcheck glTexSubImage2D((GLenum)get_target(), level(), 0, 0, width(), height(), (GLenum)format, (GLenum)type, src);
|
||||
}
|
||||
|
||||
void copy_from(buffer &buf, u32 gl_format_type, u32 offset, u32 length)
|
||||
void copy_from(const buffer &buf, gl::texture::sized_internal_format format, u32 offset, u32 length)
|
||||
{
|
||||
if (get_target() != target::texture_buffer)
|
||||
throw EXCEPTION("OpenGL error: texture cannot copy from buffer");
|
||||
|
||||
if (!offset)
|
||||
{
|
||||
copy_from(buf, gl_format_type);
|
||||
copy_from(buf, format);
|
||||
return;
|
||||
}
|
||||
|
||||
if (glTextureBufferRangeEXT == nullptr)
|
||||
throw EXCEPTION("OpenGL error: partial buffer access for textures is unsupported on your system");
|
||||
|
||||
__glcheck glTextureBufferRangeEXT(id(), (GLenum)target::texture_buffer, gl_format_type, buf.id(), offset, length);
|
||||
__glcheck glTextureBufferRangeEXT(id(), (GLenum)target::texture_buffer, (GLenum)format, buf.id(), offset, length);
|
||||
}
|
||||
|
||||
void copy_from(buffer &buf, u32 gl_format_type)
|
||||
void copy_from(const buffer &buf, gl::texture::sized_internal_format format)
|
||||
{
|
||||
save_binding_state save(*this);
|
||||
__glcheck glTexBuffer((GLenum)target::texture_buffer, gl_format_type, buf.id());
|
||||
__glcheck glTexBuffer((GLenum)target::texture_buffer, (GLenum)format, buf.id());
|
||||
}
|
||||
|
||||
void copy_from(const buffer& buf, texture::format format, texture::type type, class pixel_unpack_settings pixel_settings)
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "gl_texture_cache.h"
|
||||
#include "GLGSRender.h"
|
||||
#include "../Common/TextureUtils.h"
|
||||
#include "../rsx_utils.h"
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
@ -40,9 +41,7 @@ namespace gl
|
||||
if (found_texture)
|
||||
{
|
||||
//read from local
|
||||
LOG_WARNING(RSX, "cached_texture at 0x%x reading from local buffer", info->start_address);
|
||||
|
||||
glCopyImageSubData(
|
||||
__glcheck glCopyImageSubData(
|
||||
found_texture->gl_name, (GLenum)found_texture->info->target, 0, 0, 0, 0,
|
||||
gl_name, (GLenum)info->target, 0, 0, 0, 0,
|
||||
info->width, info->height, info->depth);
|
||||
@ -60,23 +59,92 @@ namespace gl
|
||||
|
||||
if (info->format.format == gl::texture::format::depth || info->format.format == gl::texture::format::depth_stencil)
|
||||
{
|
||||
LOG_ERROR(RSX, "cached_texture at 0x%x: unimplemented reading depth(stencil) from host buffer", info->start_address);
|
||||
gl::buffer pbo_depth;
|
||||
|
||||
//TODO
|
||||
__glcheck pbo_depth.create(info->pitch * info->height);
|
||||
__glcheck pbo_depth.map([&](GLubyte* pixels)
|
||||
{
|
||||
switch (info->format.bpp)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
u16 *dst = (u16*)pixels;
|
||||
const be_t<u16>* src = (const be_t<u16>*)vm::base_priv(info->start_address);
|
||||
for (u32 i = 0, end = info->pitch / info->format.bpp * info->height; i < end; ++i)
|
||||
{
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
{
|
||||
u32 *dst = (u32*)pixels;
|
||||
const be_t<u32>* src = (const be_t<u32>*)vm::base_priv(info->start_address);
|
||||
for (u32 i = 0, end = info->pitch / info->format.bpp * info->height; i < end; ++i)
|
||||
{
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EXCEPTION("");
|
||||
}
|
||||
}, gl::buffer::access::write);
|
||||
|
||||
gl::pixel_unpack_settings{}
|
||||
.row_length(info->pitch / info->format.bpp)
|
||||
.aligment(1)
|
||||
.swap_bytes((info->format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none)
|
||||
.apply();
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_depth.id());
|
||||
|
||||
__glcheck 0;
|
||||
|
||||
__glcheck glTexSubImage2D((GLenum)info->target, 0, 0, 0, info->width, info->height,
|
||||
(GLenum)info->format.format, (GLenum)info->format.type, nullptr);
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
else if (info->compressed_size)
|
||||
{
|
||||
LOG_WARNING(RSX, "cached_texture at 0x%x: reading compressed texture from host buffer", info->start_address);
|
||||
|
||||
__glcheck glCompressedTexImage2D((GLenum)info->target, 0,
|
||||
__glcheck glCompressedTexSubImage2D((GLenum)info->target, 0,
|
||||
0, 0, info->width, info->height,
|
||||
(GLenum)info->format.internal_format,
|
||||
info->width, info->height,
|
||||
0,
|
||||
info->compressed_size, vm::base_priv(info->start_address));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING(RSX, "cached_texture at 0x%x reading from host buffer", info->start_address);
|
||||
void *pixels = vm::base_priv(info->start_address);
|
||||
|
||||
std::unique_ptr<u8[]> linear_pixels;
|
||||
|
||||
if (info->swizzled && (info->format.flags & texture_flags::allow_swizzle) != texture_flags::none)
|
||||
{
|
||||
linear_pixels.reset(new u8[info->size()]);
|
||||
switch (info->format.bpp)
|
||||
{
|
||||
case 1:
|
||||
rsx::convert_linear_swizzle<u8>(pixels, linear_pixels.get(), info->width, info->height, true);
|
||||
break;
|
||||
case 2:
|
||||
rsx::convert_linear_swizzle<u16>(pixels, linear_pixels.get(), info->width, info->height, true);
|
||||
break;
|
||||
case 4:
|
||||
rsx::convert_linear_swizzle<u32>(pixels, linear_pixels.get(), info->width, info->height, true);
|
||||
break;
|
||||
case 8:
|
||||
rsx::convert_linear_swizzle<u64>(pixels, linear_pixels.get(), info->width, info->height, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EXCEPTION("");
|
||||
}
|
||||
|
||||
pixels = linear_pixels.get();
|
||||
}
|
||||
|
||||
gl::pixel_unpack_settings{}
|
||||
.row_length(info->pitch / info->format.bpp)
|
||||
@ -85,7 +153,7 @@ namespace gl
|
||||
.apply();
|
||||
|
||||
__glcheck glTexSubImage2D((GLenum)info->target, 0, 0, 0, info->width, info->height,
|
||||
(GLenum)info->format.format, (GLenum)info->format.type, vm::base_priv(info->start_address));
|
||||
(GLenum)info->format.format, (GLenum)info->format.type, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,15 +162,55 @@ namespace gl
|
||||
|
||||
void cached_texture::write()
|
||||
{
|
||||
LOG_WARNING(RSX, "cached_texture at 0x%x writing to host buffer", info->start_address);
|
||||
|
||||
bind();
|
||||
|
||||
if (info->format.format == gl::texture::format::depth || info->format.format == gl::texture::format::depth_stencil)
|
||||
{
|
||||
LOG_ERROR(RSX, "cached_texture at 0x%x: unimplemented writing depth(stencil) to host buffer", info->start_address);
|
||||
gl::buffer pbo_depth;
|
||||
|
||||
//TODO
|
||||
pbo_depth.create(info->pitch * info->height);
|
||||
|
||||
gl::pixel_pack_settings{}
|
||||
.row_length(info->pitch / info->format.bpp)
|
||||
.aligment(1)
|
||||
.swap_bytes((info->format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none)
|
||||
.apply();
|
||||
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_depth.id());
|
||||
__glcheck glGetTexImage((GLenum)info->target, 0, (GLenum)info->format.format, (GLenum)info->format.type, nullptr);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
|
||||
__glcheck pbo_depth.map([&](GLubyte* pixels)
|
||||
{
|
||||
switch (info->format.bpp)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
const u16 *src = (const u16*)pixels;
|
||||
be_t<u16>* dst = (be_t<u16>*)vm::base_priv(info->start_address);
|
||||
for (u32 i = 0, end = info->pitch / info->format.bpp * info->height; i < end; ++i)
|
||||
{
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
{
|
||||
const u32 *src = (const u32*)pixels;
|
||||
be_t<u32>* dst = (be_t<u32>*)vm::base_priv(info->start_address);
|
||||
for (u32 i = 0, end = info->pitch / info->format.bpp * info->height; i < end; ++i)
|
||||
{
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EXCEPTION("");
|
||||
}
|
||||
|
||||
}, gl::buffer::access::read);
|
||||
}
|
||||
else if (info->compressed_size)
|
||||
{
|
||||
@ -110,13 +218,19 @@ namespace gl
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info->swizzled && (info->format.flags & texture_flags::allow_swizzle) != texture_flags::none)
|
||||
{
|
||||
//TODO
|
||||
LOG_ERROR(RSX, "writing swizzled texture[0x%x] to host buffer", info->start_address);
|
||||
}
|
||||
|
||||
gl::pixel_pack_settings{}
|
||||
.row_length(info->pitch / info->format.bpp)
|
||||
.aligment(1)
|
||||
.swap_bytes((info->format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none)
|
||||
.apply();
|
||||
|
||||
glGetTexImage((GLenum)info->target, 0, (GLenum)info->format.format, (GLenum)info->format.type, vm::base_priv(info->start_address));
|
||||
__glcheck glGetTexImage((GLenum)info->target, 0, (GLenum)info->format.format, (GLenum)info->format.type, vm::base_priv(info->start_address));
|
||||
}
|
||||
|
||||
ignore(gl::cache_buffers::all);
|
||||
@ -126,7 +240,7 @@ namespace gl
|
||||
{
|
||||
if (!created())
|
||||
{
|
||||
create();
|
||||
__glcheck create();
|
||||
}
|
||||
|
||||
switch (m_state)
|
||||
@ -135,7 +249,7 @@ namespace gl
|
||||
case cache_entry_state::host_synchronized:
|
||||
if ((buffers & cache_buffers::local) != cache_buffers::none)
|
||||
{
|
||||
read();
|
||||
__glcheck read();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@ -254,11 +368,9 @@ namespace gl
|
||||
|
||||
glGenTextures(1, &gl_name);
|
||||
|
||||
if (!info->compressed_size)
|
||||
{
|
||||
bind();
|
||||
__glcheck glTexStorage2D((GLenum)info->target, 1, (GLenum)info->format.internal_format, info->width, info->height);
|
||||
}
|
||||
bind();
|
||||
__glcheck glTexStorage2D((GLenum)info->target, 1, (GLenum)info->format.internal_format, info->width, info->height);
|
||||
//__glcheck glClearTexImage(gl_name, 0, (GLenum)info->format.format, (GLenum)info->format.type, nullptr);
|
||||
}
|
||||
|
||||
void cached_texture::remove()
|
||||
@ -331,7 +443,7 @@ namespace gl
|
||||
|
||||
if (m_current_protection != flags)
|
||||
{
|
||||
LOG_WARNING(RSX, "protection region [0x%x, 0x%x)", start_address, start_address + size());
|
||||
LOG_WARNING(RSX, "protected region [0x%x, 0x%x)", start_address, start_address + size());
|
||||
vm::page_protect(start_address, size(), 0, m_current_protection & ~flags, flags);
|
||||
m_current_protection = flags;
|
||||
}
|
||||
@ -449,8 +561,31 @@ namespace gl
|
||||
|
||||
cached_texture &texture_cache::entry(const texture_info &info, cache_buffers sync)
|
||||
{
|
||||
u32 aligned_address = info.start_address & ~(vm::page_size - 1);
|
||||
u32 aligned_size = align(info.size(), vm::page_size);
|
||||
//u32 aligned_address = info.start_address & ~(vm::page_size - 1);
|
||||
u32 aligned_address;
|
||||
u32 aligned_size;
|
||||
|
||||
const bool accurate_cache = false;
|
||||
|
||||
if (accurate_cache)
|
||||
{
|
||||
aligned_address = info.start_address & ~(vm::page_size - 1);
|
||||
aligned_size = align(info.start_address - aligned_address + info.size(), vm::page_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
aligned_size = info.size() & ~(vm::page_size - 1);
|
||||
|
||||
if (!aligned_size)
|
||||
{
|
||||
aligned_address = info.start_address & ~(vm::page_size - 1);
|
||||
aligned_size = align(info.size() + info.start_address - aligned_address, vm::page_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
aligned_address = align(info.start_address, vm::page_size);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<protected_region*> regions = find_regions(aligned_address, aligned_size);
|
||||
protected_region *region;
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <vector>
|
||||
#include "Utilities/types.h"
|
||||
#include "gl_helpers.h"
|
||||
#include <array>
|
||||
|
||||
namespace gl
|
||||
{
|
||||
@ -63,6 +64,7 @@ namespace gl
|
||||
|
||||
texture::target target;
|
||||
texture_format format;
|
||||
bool swizzled;
|
||||
|
||||
u32 start_address;
|
||||
|
||||
|
@ -136,7 +136,7 @@ int wrap(int wrap)
|
||||
}
|
||||
|
||||
|
||||
void rsx::gl_texture::bind(gl::texture_cache& cache, int index, rsx::texture& tex)
|
||||
void rsx::gl_texture::bind(gl::texture_cache& cache, rsx::texture& tex)
|
||||
{
|
||||
u32 full_format = tex.format();
|
||||
u32 format = full_format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||
@ -145,7 +145,7 @@ void rsx::gl_texture::bind(gl::texture_cache& cache, int index, rsx::texture& te
|
||||
|
||||
gl::texture::target target = is_normalized ? gl::texture::target::texture2D : gl::texture::target::texture_rectangle;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
glActiveTexture(GL_TEXTURE0 + tex.index());
|
||||
gl::texture_view(target, 0).bind();
|
||||
|
||||
if (!tex.enabled())
|
||||
@ -166,6 +166,7 @@ void rsx::gl_texture::bind(gl::texture_cache& cache, int index, rsx::texture& te
|
||||
info.dimension = tex.dimension();
|
||||
info.start_address = rsx::get_address(tex.offset(), tex.location());
|
||||
info.target = target;
|
||||
info.swizzled = is_swizzled;
|
||||
|
||||
if (is_compressed)
|
||||
{
|
||||
@ -218,7 +219,7 @@ void rsx::gl_texture::bind(gl::texture_cache& cache, int index, rsx::texture& te
|
||||
remap = info.format.remap.data();
|
||||
}
|
||||
|
||||
__glcheck cache.entry(info, gl::cache_buffers::local).bind(index);
|
||||
__glcheck cache.entry(info, gl::cache_buffers::local).bind(tex.index());
|
||||
|
||||
__glcheck glTexParameteri((GLenum)target, GL_TEXTURE_MAX_LEVEL, tex.mipmap() - 1);
|
||||
__glcheck glTexParameteri((GLenum)target, GL_GENERATE_MIPMAP, tex.mipmap() > 1);
|
||||
|
@ -18,7 +18,7 @@ namespace rsx
|
||||
|
||||
namespace gl_texture
|
||||
{
|
||||
void bind(gl::texture_cache& cache, int index, rsx::texture& tex);
|
||||
void bind(gl::texture_cache& cache, rsx::texture& tex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,6 +210,11 @@ namespace rsx
|
||||
return method_registers[NV4097_SET_TEXTURE_CONTROL3 + m_index] & 0xfffff;
|
||||
}
|
||||
|
||||
u8 texture::index() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
void vertex_texture::init(u8 index)
|
||||
{
|
||||
m_index = index;
|
||||
@ -393,4 +398,9 @@ namespace rsx
|
||||
{
|
||||
return method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL3 + (m_index * 8)] & 0xfffff;
|
||||
}
|
||||
|
||||
u8 vertex_texture::index() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
}
|
@ -561,7 +561,10 @@ namespace rsx
|
||||
else
|
||||
{
|
||||
++m_internal_task_waiters;
|
||||
add_internal_task(callback).wait();
|
||||
while (add_internal_task(callback).wait_for(1s) == std::future_status::timeout)
|
||||
{
|
||||
CHECK_EMU_STATUS;
|
||||
}
|
||||
--m_internal_task_waiters;
|
||||
}
|
||||
}
|
||||
@ -737,6 +740,9 @@ namespace rsx
|
||||
method_registers[NV4097_SET_BLEND_COLOR2] = 0;
|
||||
method_registers[NV4097_SET_BLEND_EQUATION] = (CELL_GCM_FUNC_ADD << 16) | CELL_GCM_FUNC_ADD;
|
||||
|
||||
method_registers[NV4097_SET_STENCIL_TEST_ENABLE] = false;
|
||||
method_registers[NV4097_SET_DEPTH_TEST_ENABLE] = false;
|
||||
|
||||
method_registers[NV4097_SET_STENCIL_MASK] = 0xff;
|
||||
method_registers[NV4097_SET_STENCIL_FUNC] = CELL_GCM_ALWAYS;
|
||||
method_registers[NV4097_SET_STENCIL_FUNC_REF] = 0x00;
|
||||
|
Loading…
x
Reference in New Issue
Block a user