rsx: Texture cache fixes and improvments

gl/vk/rsx: Refactoring; unify texture cache code
gl: Fixups
- Removes rsx::gl::texture class and leave gl::texture intact
- Simplify texture create and upload mechanisms
- Re-enable texture uploads with the new texture cache mechanism
rsx: texture cache - check if bit region fits into dst texture before attempting to copy
gl/vk: Cleanup
- Set initial texture layout to DST_OPTIMAL since it has no data in it anyway at the start
- Move structs outside of classes to avoid clutter
This commit is contained in:
kd-11 2017-09-08 17:52:13 +03:00
parent 07c83f6e44
commit e37a2a8f7d
26 changed files with 2438 additions and 3083 deletions

View file

@ -5,7 +5,6 @@
#include "../RSXThread.h"
#include "../RSXTexture.h"
#include "../rsx_utils.h"
#include "../Common/TextureUtils.h"
namespace gl
{
@ -162,20 +161,20 @@ namespace gl
}
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_FILTER, min_filter);
glSamplerParameterf(samplerHandle, GL_TEXTURE_LOD_BIAS, 0.f);
glSamplerParameterf(samplerHandle, GL_TEXTURE_MIN_LOD, -1000.f);
glSamplerParameterf(samplerHandle, GL_TEXTURE_MAX_LOD, 1000.f);
glSamplerParameterf(samplerHandle, GL_TEXTURE_LOD_BIAS, 0.f);
glSamplerParameterf(samplerHandle, GL_TEXTURE_MIN_LOD, -1000.f);
glSamplerParameterf(samplerHandle, GL_TEXTURE_MAX_LOD, 1000.f);
}
else
{
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_FILTER, tex_min_filter(tex.min_filter()));
glSamplerParameterf(samplerHandle, GL_TEXTURE_LOD_BIAS, tex.bias());
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8));
glSamplerParameteri(samplerHandle, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8));
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_FILTER, tex_min_filter(tex.min_filter()));
glSamplerParameterf(samplerHandle, GL_TEXTURE_LOD_BIAS, tex.bias());
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8));
glSamplerParameteri(samplerHandle, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8));
}
glSamplerParameteri(samplerHandle, GL_TEXTURE_MAG_FILTER, tex_mag_filter(tex.mag_filter()));
glSamplerParameterf(samplerHandle, GL_TEXTURE_MAX_ANISOTROPY_EXT, ::gl::max_aniso(tex.max_aniso()));
glSamplerParameteri(samplerHandle, GL_TEXTURE_MAG_FILTER, tex_mag_filter(tex.mag_filter()));
glSamplerParameterf(samplerHandle, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso(tex.max_aniso()));
const u32 texture_format = tex.format() & ~(CELL_GCM_TEXTURE_UN | CELL_GCM_TEXTURE_LN);
if (texture_format == CELL_GCM_TEXTURE_DEPTH16 || texture_format == CELL_GCM_TEXTURE_DEPTH24_D8)
@ -197,10 +196,7 @@ namespace gl
else
glSamplerParameteri(samplerHandle, GL_TEXTURE_COMPARE_MODE, GL_NONE);
}
}
namespace
{
bool is_compressed_format(u32 texture_format)
{
switch (texture_format)
@ -234,23 +230,6 @@ namespace
fmt::throw_exception("Unknown format 0x%x" HERE, texture_format);
}
bool requires_unpack_byte(u32 texture_format)
{
switch (texture_format)
{
case CELL_GCM_TEXTURE_R5G6B5:
case CELL_GCM_TEXTURE_X16:
case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
case CELL_GCM_TEXTURE_Y16_X16:
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
case CELL_GCM_TEXTURE_D1R5G5B5:
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
return true;
}
return false;
}
std::array<GLenum, 4> get_swizzle_remap(u32 texture_format)
{
// NOTE: This must be in ARGB order in all forms below.
@ -270,307 +249,253 @@ namespace
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
return { GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE };
return{ GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE };
case CELL_GCM_TEXTURE_A4R4G4B4:
return { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA };
return{ GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA };
case CELL_GCM_TEXTURE_B8:
case CELL_GCM_TEXTURE_X16:
case CELL_GCM_TEXTURE_X32_FLOAT:
return { GL_RED, GL_RED, GL_RED, GL_RED };
return{ GL_RED, GL_RED, GL_RED, GL_RED };
case CELL_GCM_TEXTURE_G8B8:
return { GL_GREEN, GL_RED, GL_GREEN, GL_RED};
case CELL_GCM_TEXTURE_G8B8:
return{ GL_GREEN, GL_RED, GL_GREEN, GL_RED };
case CELL_GCM_TEXTURE_Y16_X16:
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
return { GL_RED, GL_GREEN, GL_RED, GL_GREEN};
return{ GL_RED, GL_GREEN, GL_RED, GL_GREEN };
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
return { GL_RED, GL_ALPHA, GL_BLUE, GL_GREEN };
return{ GL_RED, GL_ALPHA, GL_BLUE, GL_GREEN };
case CELL_GCM_TEXTURE_D1R5G5B5:
case CELL_GCM_TEXTURE_D8R8G8B8:
return { GL_ONE, GL_RED, GL_GREEN, GL_BLUE };
case CELL_GCM_TEXTURE_D8R8G8B8:
return{ GL_ONE, GL_RED, GL_GREEN, GL_BLUE };
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
return { GL_RED, GL_GREEN, GL_RED, GL_GREEN };
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
return{ GL_RED, GL_GREEN, GL_RED, GL_GREEN };
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
return { GL_ZERO, GL_GREEN, GL_BLUE, GL_RED };
return{ GL_ZERO, GL_GREEN, GL_BLUE, GL_RED };
}
fmt::throw_exception("Unknown format 0x%x" HERE, texture_format);
}
}
namespace rsx
{
namespace gl
GLuint create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, rsx::texture_dimension_extended type)
{
static const int gl_tex_zfunc[] =
if (is_compressed_format(gcm_format))
{
GL_NEVER,
GL_LESS,
GL_EQUAL,
GL_LEQUAL,
GL_GREATER,
GL_NOTEQUAL,
GL_GEQUAL,
GL_ALWAYS,
};
void texture::create()
{
if (m_id)
{
remove();
}
glGenTextures(1, &m_id);
//Compressed formats have a 4-byte alignment
//TODO: Verify that samplers are not affected by the padding
width = align(width, 4);
height = align(height, 4);
}
u16 texture::get_pitch_modifier(u32 format)
GLuint id = 0;
GLenum target;
GLenum internal_format = get_sized_internal_format(gcm_format);
glGenTextures(1, &id);
switch (type)
{
switch (format)
{
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
default:
LOG_ERROR(RSX, "Unimplemented pitch modifier for texture format: 0x%x", format);
return 0;
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
return 4;
case CELL_GCM_TEXTURE_B8:
return 1;
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
return 0;
case CELL_GCM_TEXTURE_A1R5G5B5:
case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G6B5:
case CELL_GCM_TEXTURE_G8B8:
case CELL_GCM_TEXTURE_R6G5B5:
case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
case CELL_GCM_TEXTURE_X16:
case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_D1R5G5B5:
return 2;
case CELL_GCM_TEXTURE_A8R8G8B8:
case CELL_GCM_TEXTURE_X32_FLOAT:
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
case CELL_GCM_TEXTURE_D8R8G8B8:
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
case CELL_GCM_TEXTURE_DEPTH24_D8:
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
case CELL_GCM_TEXTURE_Y16_X16:
return 4;
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
return 8;
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
return 16;
}
case rsx::texture_dimension_extended::texture_dimension_1d:
target = GL_TEXTURE_1D;
glBindTexture(GL_TEXTURE_1D, id);
glTexStorage1D(GL_TEXTURE_1D, mipmaps, internal_format, width);
break;
case rsx::texture_dimension_extended::texture_dimension_2d:
target = GL_TEXTURE_2D;
glBindTexture(GL_TEXTURE_2D, id);
glTexStorage2D(GL_TEXTURE_2D, mipmaps, internal_format, width, height);
break;
case rsx::texture_dimension_extended::texture_dimension_3d:
target = GL_TEXTURE_3D;
glBindTexture(GL_TEXTURE_3D, id);
glTexStorage3D(GL_TEXTURE_3D, mipmaps, internal_format, width, height, depth);
break;
case rsx::texture_dimension_extended::texture_dimension_cubemap:
target = GL_TEXTURE_CUBE_MAP;
glBindTexture(GL_TEXTURE_CUBE_MAP, id);
glTexStorage2D(GL_TEXTURE_CUBE_MAP, mipmaps, internal_format, width, height);
break;
}
namespace
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
return id;
}
void fill_texture(rsx::texture_dimension_extended dim, u16 mipmap_count, int format, u16 width, u16 height, u16 depth,
const std::vector<rsx_subresource_layout> &input_layouts, bool is_swizzled, std::vector<gsl::byte> staging_buffer)
{
int mip_level = 0;
if (is_compressed_format(format))
{
void create_and_fill_texture(rsx::texture_dimension_extended dim,
u16 mipmap_count, int format, u16 width, u16 height, u16 depth, const std::vector<rsx_subresource_layout> &input_layouts, bool is_swizzled,
std::vector<gsl::byte> staging_buffer)
{
int mip_level = 0;
if (is_compressed_format(format))
{
//Compressed formats have a 4-byte alignment
//TODO: Verify that samplers are not affected by the padding
width = align(width, 4);
height = align(height, 4);
}
if (dim == rsx::texture_dimension_extended::texture_dimension_1d)
{
__glcheck glTexStorage1D(GL_TEXTURE_1D, mipmap_count, ::gl::get_sized_internal_format(format), width);
if (!is_compressed_format(format))
{
const auto &format_type = ::gl::get_format_type(format);
for (const rsx_subresource_layout &layout : input_layouts)
{
__glcheck upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
__glcheck glTexSubImage1D(GL_TEXTURE_1D, mip_level++, 0, layout.width_in_block, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
}
}
else
{
for (const rsx_subresource_layout &layout : input_layouts)
{
u32 size = layout.width_in_block * ((format == CELL_GCM_TEXTURE_COMPRESSED_DXT1) ? 8 : 16);
__glcheck upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
__glcheck glCompressedTexSubImage1D(GL_TEXTURE_1D, mip_level++, 0, layout.width_in_block * 4, ::gl::get_sized_internal_format(format), size, staging_buffer.data());
}
}
return;
}
if (dim == rsx::texture_dimension_extended::texture_dimension_2d)
{
__glcheck glTexStorage2D(GL_TEXTURE_2D, mipmap_count, ::gl::get_sized_internal_format(format), width, height);
if (!is_compressed_format(format))
{
const auto &format_type = ::gl::get_format_type(format);
for (const rsx_subresource_layout &layout : input_layouts)
{
__glcheck upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
__glcheck glTexSubImage2D(GL_TEXTURE_2D, mip_level++, 0, 0, layout.width_in_block, layout.height_in_block, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
}
}
else
{
for (const rsx_subresource_layout &layout : input_layouts)
{
u32 size = layout.width_in_block * layout.height_in_block * ((format == CELL_GCM_TEXTURE_COMPRESSED_DXT1) ? 8 : 16);
__glcheck upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
__glcheck glCompressedTexSubImage2D(GL_TEXTURE_2D, mip_level++, 0, 0, layout.width_in_block * 4, layout.height_in_block * 4, ::gl::get_sized_internal_format(format), size, staging_buffer.data());
}
}
return;
}
if (dim == rsx::texture_dimension_extended::texture_dimension_cubemap)
{
__glcheck glTexStorage2D(GL_TEXTURE_CUBE_MAP, mipmap_count, ::gl::get_sized_internal_format(format), width, height);
// Note : input_layouts size is get_exact_mipmap_count() for non cubemap texture, and 6 * get_exact_mipmap_count() for cubemap
// Thus for non cubemap texture, mip_level / mipmap_per_layer will always be rounded to 0.
// mip_level % mipmap_per_layer will always be equal to mip_level
if (!is_compressed_format(format))
{
const auto &format_type = ::gl::get_format_type(format);
for (const rsx_subresource_layout &layout : input_layouts)
{
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
__glcheck glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + mip_level / mipmap_count, mip_level % mipmap_count, 0, 0, layout.width_in_block, layout.height_in_block, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
mip_level++;
}
}
else
{
for (const rsx_subresource_layout &layout : input_layouts)
{
u32 size = layout.width_in_block * layout.height_in_block * ((format == CELL_GCM_TEXTURE_COMPRESSED_DXT1) ? 8 : 16);
__glcheck upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
__glcheck glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + mip_level / mipmap_count, mip_level % mipmap_count, 0, 0, layout.width_in_block * 4, layout.height_in_block * 4, ::gl::get_sized_internal_format(format), size, staging_buffer.data());
mip_level++;
}
}
return;
}
if (dim == rsx::texture_dimension_extended::texture_dimension_3d)
{
__glcheck glTexStorage3D(GL_TEXTURE_3D, mipmap_count, ::gl::get_sized_internal_format(format), width, height, depth);
if (!is_compressed_format(format))
{
const auto &format_type = ::gl::get_format_type(format);
for (const rsx_subresource_layout &layout : input_layouts)
{
__glcheck upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
__glcheck glTexSubImage3D(GL_TEXTURE_3D, mip_level++, 0, 0, 0, layout.width_in_block, layout.height_in_block, depth, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
}
}
else
{
for (const rsx_subresource_layout &layout : input_layouts)
{
u32 size = layout.width_in_block * layout.height_in_block * layout.depth * ((format == CELL_GCM_TEXTURE_COMPRESSED_DXT1) ? 8 : 16);
__glcheck upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
__glcheck glCompressedTexSubImage3D(GL_TEXTURE_3D, mip_level++, 0, 0, 0, layout.width_in_block * 4, layout.height_in_block * 4, layout.depth, ::gl::get_sized_internal_format(format), size, staging_buffer.data());
}
}
return;
}
}
//Compressed formats have a 4-byte alignment
//TODO: Verify that samplers are not affected by the padding
width = align(width, 4);
height = align(height, 4);
}
bool texture::mandates_expansion(u32 format)
if (dim == rsx::texture_dimension_extended::texture_dimension_1d)
{
/**
* If a texture behaves differently when uploaded directly vs when uploaded via texutils methods, it should be added here.
*/
if (format == CELL_GCM_TEXTURE_A1R5G5B5)
return true;
return false;
glTexStorage1D(GL_TEXTURE_1D, mipmap_count, get_sized_internal_format(format), width);
if (!is_compressed_format(format))
{
const auto &format_type = get_format_type(format);
for (const rsx_subresource_layout &layout : input_layouts)
{
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
glTexSubImage1D(GL_TEXTURE_1D, mip_level++, 0, layout.width_in_block, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
}
}
else
{
for (const rsx_subresource_layout &layout : input_layouts)
{
u32 size = layout.width_in_block * ((format == CELL_GCM_TEXTURE_COMPRESSED_DXT1) ? 8 : 16);
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
glCompressedTexSubImage1D(GL_TEXTURE_1D, mip_level++, 0, layout.width_in_block * 4, get_sized_internal_format(format), size, staging_buffer.data());
}
}
return;
}
void texture::init(int index, rsx::fragment_texture& tex)
if (dim == rsx::texture_dimension_extended::texture_dimension_2d)
{
switch (tex.dimension())
if (!is_compressed_format(format))
{
case rsx::texture_dimension::dimension3d:
if (!tex.depth())
const auto &format_type = get_format_type(format);
for (const rsx_subresource_layout &layout : input_layouts)
{
return;
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
glTexSubImage2D(GL_TEXTURE_2D, mip_level++, 0, 0, layout.width_in_block, layout.height_in_block, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
}
case rsx::texture_dimension::dimension2d:
if (!tex.height())
{
return;
}
case rsx::texture_dimension::dimension1d:
if (!tex.width())
{
return;
}
break;
}
const u32 texaddr = rsx::get_address(tex.offset(), tex.location());
//We can't re-use texture handles if using immutable storage
if (m_id)
else
{
__glcheck remove();
for (const rsx_subresource_layout &layout : input_layouts)
{
u32 size = layout.width_in_block * layout.height_in_block * ((format == CELL_GCM_TEXTURE_COMPRESSED_DXT1) ? 8 : 16);
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
glCompressedTexSubImage2D(GL_TEXTURE_2D, mip_level++, 0, 0, layout.width_in_block * 4, layout.height_in_block * 4, get_sized_internal_format(format), size, staging_buffer.data());
}
}
__glcheck create();
return;
}
__glcheck glActiveTexture(GL_TEXTURE0 + index);
bind();
if (dim == rsx::texture_dimension_extended::texture_dimension_cubemap)
{
// Note : input_layouts size is get_exact_mipmap_count() for non cubemap texture, and 6 * get_exact_mipmap_count() for cubemap
// Thus for non cubemap texture, mip_level / mipmap_per_layer will always be rounded to 0.
// mip_level % mipmap_per_layer will always be equal to mip_level
if (!is_compressed_format(format))
{
const auto &format_type = get_format_type(format);
for (const rsx_subresource_layout &layout : input_layouts)
{
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + mip_level / mipmap_count, mip_level % mipmap_count, 0, 0, layout.width_in_block, layout.height_in_block, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
mip_level++;
}
}
else
{
for (const rsx_subresource_layout &layout : input_layouts)
{
u32 size = layout.width_in_block * layout.height_in_block * ((format == CELL_GCM_TEXTURE_COMPRESSED_DXT1) ? 8 : 16);
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + mip_level / mipmap_count, mip_level % mipmap_count, 0, 0, layout.width_in_block * 4, layout.height_in_block * 4, get_sized_internal_format(format), size, staging_buffer.data());
mip_level++;
}
}
return;
}
u32 full_format = tex.format();
if (dim == rsx::texture_dimension_extended::texture_dimension_3d)
{
if (!is_compressed_format(format))
{
const auto &format_type = get_format_type(format);
for (const rsx_subresource_layout &layout : input_layouts)
{
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
glTexSubImage3D(GL_TEXTURE_3D, mip_level++, 0, 0, 0, layout.width_in_block, layout.height_in_block, depth, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
}
}
else
{
for (const rsx_subresource_layout &layout : input_layouts)
{
u32 size = layout.width_in_block * layout.height_in_block * layout.depth * ((format == CELL_GCM_TEXTURE_COMPRESSED_DXT1) ? 8 : 16);
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
glCompressedTexSubImage3D(GL_TEXTURE_3D, mip_level++, 0, 0, 0, layout.width_in_block * 4, layout.height_in_block * 4, layout.depth, get_sized_internal_format(format), size, staging_buffer.data());
}
}
return;
}
}
u32 format = full_format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
bool is_swizzled = !!(~full_format & CELL_GCM_TEXTURE_LN);
void upload_texture(const GLuint id, const u32 texaddr, const u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, bool is_swizzled, rsx::texture_dimension_extended type,
std::vector<rsx_subresource_layout>& subresources_layout, std::pair<std::array<u8, 4>, std::array<u8, 4>>& decoded_remap, bool static_state)
{
const bool is_cubemap = type == rsx::texture_dimension_extended::texture_dimension_cubemap;
size_t texture_data_sz = get_placed_texture_storage_size(width, height, depth, gcm_format, mipmaps, is_cubemap, 256, 512);
std::vector<gsl::byte> data_upload_buf(texture_data_sz);
__glcheck ::gl::pixel_pack_settings().apply();
__glcheck ::gl::pixel_unpack_settings().apply();
const std::array<GLenum, 4>& glRemap = get_swizzle_remap(gcm_format);
u32 aligned_pitch = tex.pitch();
GLenum target;
GLenum remap_values[4];
size_t texture_data_sz = get_placed_texture_storage_size(tex, 256);
std::vector<gsl::byte> data_upload_buf(texture_data_sz);
u32 block_sz = get_pitch_modifier(format);
switch (type)
{
case rsx::texture_dimension_extended::texture_dimension_1d:
target = GL_TEXTURE_1D;
break;
case rsx::texture_dimension_extended::texture_dimension_2d:
target = GL_TEXTURE_2D;
break;
case rsx::texture_dimension_extended::texture_dimension_3d:
target = GL_TEXTURE_3D;
break;
case rsx::texture_dimension_extended::texture_dimension_cubemap:
target = GL_TEXTURE_CUBE_MAP;
break;
}
__glcheck glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glBindTexture(target, id);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1);
__glcheck create_and_fill_texture(tex.get_extended_texture_dimension(), tex.get_exact_mipmap_count(), format, tex.width(), tex.height(), tex.depth(), get_subresources_layout(tex), is_swizzled, data_upload_buf);
if (static_state)
{
//Usually for vertex textures
const std::array<GLenum, 4>& glRemap = get_swizzle_remap(format);
glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, glRemap[0]);
glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, glRemap[1]);
glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, glRemap[2]);
glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, glRemap[3]);
glTexParameteri(m_target, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, tex.get_exact_mipmap_count() - 1);
auto decoded_remap = tex.decoded_remap();
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f);
}
else
{
//Remapping tables; format is A-R-G-B
//Remap input table. Contains channel index to read color from
const auto remap_inputs = decoded_remap.first;
@ -578,8 +503,6 @@ namespace rsx
//Remap control table. Controls whether the remap value is used, or force either 0 or 1
const auto remap_lookup = decoded_remap.second;
GLenum remap_values[4];
for (u8 channel = 0; channel < 4; ++channel)
{
switch (remap_lookup[channel])
@ -598,109 +521,14 @@ namespace rsx
}
}
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, remap_values[0]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, remap_values[1]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, remap_values[2]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, remap_values[3]);
//The rest of sampler state is now handled by sampler state objects
glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, remap_values[0]);
glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, remap_values[1]);
glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, remap_values[2]);
glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, remap_values[3]);
}
void texture::init(int index, rsx::vertex_texture& tex)
{
switch (tex.dimension())
{
case rsx::texture_dimension::dimension3d:
if (!tex.depth())
{
return;
}
//The rest of sampler state is now handled by sampler state objects
case rsx::texture_dimension::dimension2d:
if (!tex.height())
{
return;
}
case rsx::texture_dimension::dimension1d:
if (!tex.width())
{
return;
}
break;
}
const u32 texaddr = rsx::get_address(tex.offset(), tex.location());
//We can't re-use texture handles if using immutable storage
if (m_id)
{
__glcheck remove();
}
__glcheck create();
__glcheck glActiveTexture(GL_TEXTURE0 + index);
bind();
u32 full_format = tex.format();
u32 format = full_format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
bool is_swizzled = !!(~full_format & CELL_GCM_TEXTURE_LN);
__glcheck::gl::pixel_pack_settings().apply();
__glcheck::gl::pixel_unpack_settings().apply();
u32 aligned_pitch = tex.pitch();
size_t texture_data_sz = get_placed_texture_storage_size(tex, 256);
std::vector<gsl::byte> data_upload_buf(texture_data_sz);
u32 block_sz = get_pitch_modifier(format);
__glcheck glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
__glcheck create_and_fill_texture(tex.get_extended_texture_dimension(), tex.get_exact_mipmap_count(), format, tex.width(), tex.height(), tex.depth(), get_subresources_layout(tex), is_swizzled, data_upload_buf);
const std::array<GLenum, 4>& glRemap = get_swizzle_remap(format);
glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, tex.get_exact_mipmap_count() - 1);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[0]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[1]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[2]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[3]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_S, GL_REPEAT);
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_T, GL_REPEAT);
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_R, GL_REPEAT);
__glcheck glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
__glcheck glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
__glcheck glTexParameterf(m_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f);
}
void texture::bind()
{
glBindTexture(m_target, m_id);
}
void texture::unbind()
{
glBindTexture(m_target, 0);
}
void texture::remove()
{
if (m_id)
{
glDeleteTextures(1, &m_id);
m_id = 0;
}
}
u32 texture::id() const
{
return m_id;
}
fill_texture(type, mipmaps, gcm_format, width, height, depth, subresources_layout, is_swizzled, data_upload_buf);
}
}