Implemented depth(stencil) textures reading/writing

Implemented swizzled textures reading
Minor fixes
This commit is contained in:
DHrpcs3 2016-03-08 16:45:06 +03:00
parent 8e57cf8da8
commit 220d48a980
9 changed files with 280 additions and 72 deletions

View File

@ -31,21 +31,69 @@ namespace
throw EXCEPTION("Unknow depth format"); 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... * 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 * 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 }; static const gl::texture::sized_internal_format vec1_types[]
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! gl::texture::sized_internal_format::r16,
const u32 vec4_types[] = { GL_RGBA16, GL_RGBA32F, GL_RGBA16F, GL_RGBA8, GL_RGBA16I, GL_RGBA16, GL_RGBA8UI }; 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) if (type > rsx::vertex_base_type::ub256)
{
throw EXCEPTION("OpenGL error: unknown vertex base type 0x%X.", (u32)type); throw EXCEPTION("OpenGL error: unknown vertex base type 0x%X.", (u32)type);
}
return vec_selectors[size][(int)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]) 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 & 2, GL_BLEND, 1);
__glcheck enable(blend_mrt & 4, GL_BLEND, GL_COLOR_ATTACHMENT2); __glcheck enable(blend_mrt & 4, GL_BLEND, 2);
__glcheck enable(blend_mrt & 8, GL_BLEND, GL_COLOR_ATTACHMENT3); __glcheck enable(blend_mrt & 8, GL_BLEND, 3);
} }
if (__glcheck enable(rsx::method_registers[NV4097_SET_LOGIC_OP_ENABLE], GL_LOGIC_OP)) 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::ub: return gl::buffer_pointer::type::u8;
case rsx::vertex_base_type::s32k: return gl::buffer_pointer::type::s32; 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::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"); throw EXCEPTION("unknow vertex type");
} }
@ -389,7 +437,7 @@ void GLGSRender::end()
int location; int location;
if (m_program->uniforms.has_location("tex" + std::to_string(i), &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); __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); 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 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 &buffer = m_gl_attrib_buffers[index].buffer;
auto &texture = m_gl_attrib_buffers[index].texture; auto &texture = m_gl_attrib_buffers[index].texture;
@ -530,7 +578,7 @@ void GLGSRender::end()
if (!enabled) if (!enabled)
{ {
glActiveTexture(GL_TEXTURE0 + index + rsx::limits::textures_count); 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); glProgramUniform1i(m_program->id(), location, index + rsx::limits::textures_count);
continue; continue;
} }
@ -573,16 +621,11 @@ void GLGSRender::end()
vertex_arrays_offsets[index] = gsl::narrow<u32>(position); vertex_arrays_offsets[index] = gsl::narrow<u32>(position);
vertex_arrays_data.resize(position + size); vertex_arrays_data.resize(position + size);
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);
u32 data_size = element_size * vertex_draw_count;
auto& attrib_pair = m_gl_attrib_buffers[index]; auto& attrib_pair = m_gl_attrib_buffers[index];
__glcheck 0; attrib_pair.buffer.data(vertex_array.size(), vertex_array.data());
attrib_pair.buffer.data(data_size, vertex_array.data());
__glcheck 0;
//Attach buffer to texture //Attach buffer to texture
attrib_pair.texture.copy_from(attrib_pair.buffer, gl_type); attrib_pair.texture.copy_from(attrib_pair.buffer, gl_type);
@ -601,12 +644,11 @@ void GLGSRender::end()
case rsx::vertex_base_type::f: 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 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); gl::texture::sized_internal_format gl_type = to_gl_internal_type(vertex_info.type, vertex_info.size);
const size_t data_size = vertex_data.size();
auto& attrib_pair = m_gl_attrib_buffers[index]; 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 //Attach buffer to texture
attrib_pair.texture.copy_from(attrib_pair.buffer, gl_type); attrib_pair.texture.copy_from(attrib_pair.buffer, gl_type);
@ -623,7 +665,7 @@ void GLGSRender::end()
else else
{ {
glActiveTexture(GL_TEXTURE0 + index + rsx::limits::textures_count); 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); glProgramUniform1i(m_program->id(), location, index + rsx::limits::textures_count);
continue; 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 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.width = width;
info.height = height; 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.compressed_size = 0;
info.target = gl::texture::target::texture2D; info.target = gl::texture::target::texture2D;
info.dimension = 2; info.dimension = 2;
//TODO
info.swizzled = false;
info.start_address = rsx::get_address(offset, location); info.start_address = rsx::get_address(offset, location);
info.format = gl::get_texture_format(surface_format_to_texture_format(format)); 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 location = rsx::method_registers[mr_color_dma[index]];
u32 pitch = rsx::method_registers[mr_color_pitch[index]]; u32 pitch = rsx::method_registers[mr_color_pitch[index]];
if (!location) if (pitch <= 64)
{ {
cached_color_buffers[index] = nullptr; cached_color_buffers[index] = nullptr;
draw_fbo.color[index] = null_texture; 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 location = rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA];
u32 pitch = rsx::method_registers[NV4097_SET_SURFACE_PITCH_Z]; u32 pitch = rsx::method_registers[NV4097_SET_SURFACE_PITCH_Z];
if (!location) if (pitch <= 64)
{ {
cached_depth_buffer = nullptr; cached_depth_buffer = nullptr;
draw_fbo.depth_stencil = null_texture; draw_fbo.depth_stencil = null_texture;
} }
else else
{ {
gl::texture_info info; gl::texture_info info{};
info.width = m_surface.width; info.width = m_surface.width;
info.height = m_surface.height; info.height = m_surface.height;
@ -1179,6 +1223,8 @@ void GLGSRender::init_buffers(bool skip_reading)
info.compressed_size = 0; info.compressed_size = 0;
info.start_address = rsx::get_address(offset, location); info.start_address = rsx::get_address(offset, location);
info.target = gl::texture::target::texture2D; info.target = gl::texture::target::texture2D;
//TODO
info.swizzled = false;
switch (m_surface.depth_format) 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 }; info.format.remap = { GL_ZERO, GL_ZERO, GL_ZERO, GL_ZERO };
__glcheck 0;
cached_depth_buffer = &m_texture_cache.entry(info, skip_reading ? gl::cache_buffers::none : gl::cache_buffers::local); __glcheck cached_depth_buffer = &m_texture_cache.entry(info, skip_reading ? gl::cache_buffers::none : gl::cache_buffers::local);
switch (m_surface.depth_format) switch (m_surface.depth_format)
{ {
case rsx::surface_depth_format::z16: case rsx::surface_depth_format::z16:
draw_fbo.depth = cached_depth_buffer->view(); __glcheck draw_fbo.depth = cached_depth_buffer->view();
break; break;
case rsx::surface_depth_format::z24s8: case rsx::surface_depth_format::z24s8:
draw_fbo.depth_stencil = cached_depth_buffer->view(); __glcheck draw_fbo.depth_stencil = cached_depth_buffer->view();
break; break;
} }
} }
} }
draw_fbo.bind(); __glcheck draw_fbo.bind();
{ {
auto info = rsx::get_active_color_surfaces(); auto info = rsx::get_active_color_surfaces();
@ -1233,7 +1279,7 @@ void GLGSRender::init_buffers(bool skip_reading)
GL_COLOR_ATTACHMENT3 GL_COLOR_ATTACHMENT3
}; };
glDrawBuffers(info.second, color_buffers + info.first); __glcheck glDrawBuffers(info.second, color_buffers + info.first);
} }
set_viewport(); 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)) 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) if (is_writing)
{ {

View File

@ -173,6 +173,10 @@ OPENGL_PROC(PFNGLTEXTUREBUFFERRANGEEXTPROC, TextureBufferRangeEXT);
OPENGL_PROC(PFNGLTEXSTORAGE1DPROC, TexStorage1D); OPENGL_PROC(PFNGLTEXSTORAGE1DPROC, TexStorage1D);
OPENGL_PROC(PFNGLTEXSTORAGE2DPROC, TexStorage2D); OPENGL_PROC(PFNGLTEXSTORAGE2DPROC, TexStorage2D);
OPENGL_PROC(PFNGLTEXSTORAGE3DPROC, TexStorage3D); OPENGL_PROC(PFNGLTEXSTORAGE3DPROC, TexStorage3D);
OPENGL_PROC(PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC, CompressedTexSubImage1D);
OPENGL_PROC(PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC, CompressedTexSubImage2D);
OPENGL_PROC(PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC, CompressedTexSubImage3D);
OPENGL_PROC(PFNGLCLEARTEXIMAGEPROC, ClearTexImage);
//ARB_Copy_Image //ARB_Copy_Image
OPENGL_PROC(PFNGLCOPYIMAGESUBDATAPROC, CopyImageSubData); OPENGL_PROC(PFNGLCOPYIMAGESUBDATAPROC, CopyImageSubData);

View File

@ -810,6 +810,7 @@ namespace gl
r32f = GL_R32F, r32f = GL_R32F,
r8ui = GL_R8UI, r8ui = GL_R8UI,
r8i = GL_R8I, r8i = GL_R8I,
r16 = GL_R16,
r16ui = GL_R16UI, r16ui = GL_R16UI,
r16i = GL_R16I, r16i = GL_R16I,
r32ui = GL_R32UI, r32ui = GL_R32UI,
@ -820,6 +821,7 @@ namespace gl
rg32f = GL_RG32F, rg32f = GL_RG32F,
rg8ui = GL_RG8UI, rg8ui = GL_RG8UI,
rg8i = GL_RG8I, rg8i = GL_RG8I,
rg16 = GL_RG16,
rg16ui = GL_RG16UI, rg16ui = GL_RG16UI,
rg16i = GL_RG16I, rg16i = GL_RG16I,
rg32ui = GL_RG32UI, rg32ui = GL_RG32UI,
@ -830,6 +832,7 @@ namespace gl
rgb8_snorm = GL_RGB8_SNORM, rgb8_snorm = GL_RGB8_SNORM,
r11f_g11f_b10f = GL_R11F_G11F_B10F, r11f_g11f_b10f = GL_R11F_G11F_B10F,
rgb9_e5 = GL_RGB9_E5, rgb9_e5 = GL_RGB9_E5,
rgb16 = GL_RGB16,
rgb16f = GL_RGB16F, rgb16f = GL_RGB16F,
rgb32f = GL_RGB32F, rgb32f = GL_RGB32F,
rgb8ui = GL_RGB8UI, rgb8ui = GL_RGB8UI,
@ -849,6 +852,7 @@ namespace gl
rgba8ui = GL_RGBA8UI, rgba8ui = GL_RGBA8UI,
rgba8i = GL_RGBA8I, rgba8i = GL_RGBA8I,
rgb10_a2ui = GL_RGB10_A2UI, rgb10_a2ui = GL_RGB10_A2UI,
rgba16 = GL_RGBA16,
rgba16ui = GL_RGBA16UI, rgba16ui = GL_RGBA16UI,
rgba16i = GL_RGBA16I, rgba16i = GL_RGBA16I,
rgba32i = GL_RGBA32I, rgba32i = GL_RGBA32I,
@ -1203,27 +1207,27 @@ namespace gl
__glcheck glTexSubImage2D((GLenum)get_target(), level(), 0, 0, width(), height(), (GLenum)format, (GLenum)type, src); __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) if (get_target() != target::texture_buffer)
throw EXCEPTION("OpenGL error: texture cannot copy from buffer"); throw EXCEPTION("OpenGL error: texture cannot copy from buffer");
if (!offset) if (!offset)
{ {
copy_from(buf, gl_format_type); copy_from(buf, format);
return; return;
} }
if (glTextureBufferRangeEXT == nullptr) if (glTextureBufferRangeEXT == nullptr)
throw EXCEPTION("OpenGL error: partial buffer access for textures is unsupported on your system"); 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); 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) void copy_from(const buffer& buf, texture::format format, texture::type type, class pixel_unpack_settings pixel_settings)

View File

@ -3,6 +3,7 @@
#include "gl_texture_cache.h" #include "gl_texture_cache.h"
#include "GLGSRender.h" #include "GLGSRender.h"
#include "../Common/TextureUtils.h" #include "../Common/TextureUtils.h"
#include "../rsx_utils.h"
#include <exception> #include <exception>
#include <string> #include <string>
@ -40,9 +41,7 @@ namespace gl
if (found_texture) if (found_texture)
{ {
//read from local //read from local
LOG_WARNING(RSX, "cached_texture at 0x%x reading from local buffer", info->start_address); __glcheck glCopyImageSubData(
glCopyImageSubData(
found_texture->gl_name, (GLenum)found_texture->info->target, 0, 0, 0, 0, found_texture->gl_name, (GLenum)found_texture->info->target, 0, 0, 0, 0,
gl_name, (GLenum)info->target, 0, 0, 0, 0, gl_name, (GLenum)info->target, 0, 0, 0, 0,
info->width, info->height, info->depth); 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) 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) else if (info->compressed_size)
{ {
LOG_WARNING(RSX, "cached_texture at 0x%x: reading compressed texture from host buffer", info->start_address); __glcheck glCompressedTexSubImage2D((GLenum)info->target, 0,
0, 0, info->width, info->height,
__glcheck glCompressedTexImage2D((GLenum)info->target, 0,
(GLenum)info->format.internal_format, (GLenum)info->format.internal_format,
info->width, info->height,
0,
info->compressed_size, vm::base_priv(info->start_address)); info->compressed_size, vm::base_priv(info->start_address));
} }
else 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{} gl::pixel_unpack_settings{}
.row_length(info->pitch / info->format.bpp) .row_length(info->pitch / info->format.bpp)
@ -85,7 +153,7 @@ namespace gl
.apply(); .apply();
__glcheck glTexSubImage2D((GLenum)info->target, 0, 0, 0, info->width, info->height, __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() void cached_texture::write()
{ {
LOG_WARNING(RSX, "cached_texture at 0x%x writing to host buffer", info->start_address);
bind(); bind();
if (info->format.format == gl::texture::format::depth || info->format.format == gl::texture::format::depth_stencil) 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) else if (info->compressed_size)
{ {
@ -110,13 +218,19 @@ namespace gl
} }
else 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{} gl::pixel_pack_settings{}
.row_length(info->pitch / info->format.bpp) .row_length(info->pitch / info->format.bpp)
.aligment(1) .aligment(1)
.swap_bytes((info->format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none) .swap_bytes((info->format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none)
.apply(); .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); ignore(gl::cache_buffers::all);
@ -126,7 +240,7 @@ namespace gl
{ {
if (!created()) if (!created())
{ {
create(); __glcheck create();
} }
switch (m_state) switch (m_state)
@ -135,7 +249,7 @@ namespace gl
case cache_entry_state::host_synchronized: case cache_entry_state::host_synchronized:
if ((buffers & cache_buffers::local) != cache_buffers::none) if ((buffers & cache_buffers::local) != cache_buffers::none)
{ {
read(); __glcheck read();
return true; return true;
} }
break; break;
@ -254,11 +368,9 @@ namespace gl
glGenTextures(1, &gl_name); 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 glClearTexImage(gl_name, 0, (GLenum)info->format.format, (GLenum)info->format.type, nullptr);
__glcheck glTexStorage2D((GLenum)info->target, 1, (GLenum)info->format.internal_format, info->width, info->height);
}
} }
void cached_texture::remove() void cached_texture::remove()
@ -331,7 +443,7 @@ namespace gl
if (m_current_protection != flags) 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); vm::page_protect(start_address, size(), 0, m_current_protection & ~flags, flags);
m_current_protection = flags; m_current_protection = flags;
} }
@ -449,8 +561,31 @@ namespace gl
cached_texture &texture_cache::entry(const texture_info &info, cache_buffers sync) cached_texture &texture_cache::entry(const texture_info &info, cache_buffers sync)
{ {
u32 aligned_address = info.start_address & ~(vm::page_size - 1); //u32 aligned_address = info.start_address & ~(vm::page_size - 1);
u32 aligned_size = align(info.size(), vm::page_size); 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); std::vector<protected_region*> regions = find_regions(aligned_address, aligned_size);
protected_region *region; protected_region *region;

View File

@ -2,6 +2,7 @@
#include <vector> #include <vector>
#include "Utilities/types.h" #include "Utilities/types.h"
#include "gl_helpers.h" #include "gl_helpers.h"
#include <array>
namespace gl namespace gl
{ {
@ -63,6 +64,7 @@ namespace gl
texture::target target; texture::target target;
texture_format format; texture_format format;
bool swizzled;
u32 start_address; u32 start_address;

View File

@ -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 full_format = tex.format();
u32 format = full_format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); 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; 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(); gl::texture_view(target, 0).bind();
if (!tex.enabled()) 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.dimension = tex.dimension();
info.start_address = rsx::get_address(tex.offset(), tex.location()); info.start_address = rsx::get_address(tex.offset(), tex.location());
info.target = target; info.target = target;
info.swizzled = is_swizzled;
if (is_compressed) 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(); 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_TEXTURE_MAX_LEVEL, tex.mipmap() - 1);
__glcheck glTexParameteri((GLenum)target, GL_GENERATE_MIPMAP, tex.mipmap() > 1); __glcheck glTexParameteri((GLenum)target, GL_GENERATE_MIPMAP, tex.mipmap() > 1);

View File

@ -18,7 +18,7 @@ namespace rsx
namespace gl_texture namespace gl_texture
{ {
void bind(gl::texture_cache& cache, int index, rsx::texture& tex); void bind(gl::texture_cache& cache, rsx::texture& tex);
} }
} }

View File

@ -210,6 +210,11 @@ namespace rsx
return method_registers[NV4097_SET_TEXTURE_CONTROL3 + m_index] & 0xfffff; return method_registers[NV4097_SET_TEXTURE_CONTROL3 + m_index] & 0xfffff;
} }
u8 texture::index() const
{
return m_index;
}
void vertex_texture::init(u8 index) void vertex_texture::init(u8 index)
{ {
m_index = index; m_index = index;
@ -393,4 +398,9 @@ namespace rsx
{ {
return method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL3 + (m_index * 8)] & 0xfffff; return method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL3 + (m_index * 8)] & 0xfffff;
} }
u8 vertex_texture::index() const
{
return m_index;
}
} }

View File

@ -561,7 +561,10 @@ namespace rsx
else else
{ {
++m_internal_task_waiters; ++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; --m_internal_task_waiters;
} }
} }
@ -737,6 +740,9 @@ namespace rsx
method_registers[NV4097_SET_BLEND_COLOR2] = 0; 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_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_MASK] = 0xff;
method_registers[NV4097_SET_STENCIL_FUNC] = CELL_GCM_ALWAYS; method_registers[NV4097_SET_STENCIL_FUNC] = CELL_GCM_ALWAYS;
method_registers[NV4097_SET_STENCIL_FUNC_REF] = 0x00; method_registers[NV4097_SET_STENCIL_FUNC_REF] = 0x00;