Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rsx: Fix get_exact_mipmap_count and add a more convenient way to get tex dim. #1643

Merged
merged 2 commits into from
Mar 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion rpcs3/Emu/RSX/CgBinaryProgram.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ class CgBinaryDisasm
auto& vmfprog = vm::ps3::_ref<CgBinaryFragmentProgram>(ptr + vmprog.program);
u32 size;
u32 ctrl = (vmfprog.outputFromH0 ? 0 : 0x40) | (vmfprog.depthReplace ? 0xe : 0);
std::vector<texture_dimension_extended> td;
std::vector<rsx::texture_dimension_extended> td;
RSXFragmentProgram prog;
prog.size = 0, prog.addr = vm::base(ptr + vmprog.ucode), prog.offset = 0, prog.ctrl = ctrl;
GLFragmentDecompilerThread(m_glsl_shader, param_array, prog, size).Task();
Expand Down
32 changes: 16 additions & 16 deletions rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,16 @@ std::string FragmentProgramDecompiler::AddTex()
std::string sampler;
switch (m_prog.get_texture_dimension(dst.tex_num))
{
case texture_dimension_extended::texture_dimension_1d:
case rsx::texture_dimension_extended::texture_dimension_1d:
sampler = "sampler1D";
break;
case texture_dimension_extended::texture_dimension_cubemap:
case rsx::texture_dimension_extended::texture_dimension_cubemap:
sampler = "samplerCube";
break;
case texture_dimension_extended::texture_dimension_2d:
case rsx::texture_dimension_extended::texture_dimension_2d:
sampler = "sampler2D";
break;
case texture_dimension_extended::texture_dimension_3d:
case rsx::texture_dimension_extended::texture_dimension_3d:
sampler = "sampler3D";
break;
}
Expand Down Expand Up @@ -442,16 +442,16 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
case RSX_FP_OPCODE_TEX:
switch (m_prog.get_texture_dimension(dst.tex_num))
{
case texture_dimension_extended::texture_dimension_1d:
case rsx::texture_dimension_extended::texture_dimension_1d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D));
return true;
case texture_dimension_extended::texture_dimension_2d:
case rsx::texture_dimension_extended::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D));
return true;
case texture_dimension_extended::texture_dimension_cubemap:
case rsx::texture_dimension_extended::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE));
return true;
case texture_dimension_extended::texture_dimension_3d:
case rsx::texture_dimension_extended::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D));
return true;
}
Expand All @@ -460,16 +460,16 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
case RSX_FP_OPCODE_TXP:
switch (m_prog.get_texture_dimension(dst.tex_num))
{
case texture_dimension_extended::texture_dimension_1d:
case rsx::texture_dimension_extended::texture_dimension_1d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ));
return true;
case texture_dimension_extended::texture_dimension_2d:
case rsx::texture_dimension_extended::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ));
return true;
case texture_dimension_extended::texture_dimension_cubemap:
case rsx::texture_dimension_extended::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ));
return true;
case texture_dimension_extended::texture_dimension_3d:
case rsx::texture_dimension_extended::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ));
return true;
}
Expand All @@ -480,16 +480,16 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
case RSX_FP_OPCODE_TXL:
switch (m_prog.get_texture_dimension(dst.tex_num))
{
case texture_dimension_extended::texture_dimension_1d:
case rsx::texture_dimension_extended::texture_dimension_1d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD));
return true;
case texture_dimension_extended::texture_dimension_2d:
case rsx::texture_dimension_extended::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD));
return true;
case texture_dimension_extended::texture_dimension_cubemap:
case rsx::texture_dimension_extended::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD));
return true;
case texture_dimension_extended::texture_dimension_3d:
case rsx::texture_dimension_extended::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD));
return true;
}
Expand Down
50 changes: 25 additions & 25 deletions rpcs3/Emu/RSX/Common/TextureUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,32 +116,32 @@ u32 get_row_pitch_in_block(u16 width_in_block, size_t multiple_constraints_in_by
size_t divided = (width_in_block * sizeof(T) + multiple_constraints_in_byte - 1) / multiple_constraints_in_byte;
return static_cast<u32>(divided * multiple_constraints_in_byte / sizeof(T));
}

/**
* Since rsx ignore unused dimensionnality some app set them to 0.
* Use 1 value instead to be more general.
*/
std::tuple<u16, u16, u8> get_height_depth_layer(const rsx::texture &tex)
{
switch (tex.get_extended_texture_dimension())
{
case rsx::texture_dimension_extended::texture_dimension_1d: return std::make_tuple(1, 1, 1);
case rsx::texture_dimension_extended::texture_dimension_2d: return std::make_tuple(tex.height(), 1, 1);
case rsx::texture_dimension_extended::texture_dimension_cubemap: return std::make_tuple(tex.height(), 1, 6);
case rsx::texture_dimension_extended::texture_dimension_3d: return std::make_tuple(tex.height(), tex.depth(), 1);
}
throw EXCEPTION("Unsupported texture dimension");
}
}

std::vector<rsx_subresource_layout> get_subresources_layout(const rsx::texture &texture)
{
u16 w = texture.width(), h = texture.height();
u16 w = texture.width();
u16 h;
u16 depth;
u8 layer;

if (texture.dimension() == rsx::texture_dimension::dimension1d)
{
depth = 1;
layer = 1;
h = 1;
}
else if (texture.dimension() == rsx::texture_dimension::dimension2d)
{
depth = 1;
layer = texture.cubemap() ? 6 : 1;
}
else if (texture.dimension() == rsx::texture_dimension::dimension3d)
{
depth = texture.depth();
layer = 1;
}
else
throw EXCEPTION("Unsupported texture dimension %d", texture.dimension());
std::tie(h, depth, layer) = get_height_depth_layer(texture);

int format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);

Expand All @@ -152,24 +152,24 @@ std::vector<rsx_subresource_layout> get_subresources_layout(const rsx::texture &
{
case CELL_GCM_TEXTURE_D8R8G8B8:
case CELL_GCM_TEXTURE_A8R8G8B8:
return get_subresources_layout_impl<1, u32>(pixels, w, h, depth, layer, texture.mipmap(), texture.pitch(), !is_swizzled);
return get_subresources_layout_impl<1, u32>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled);
case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_D1R5G5B5:
case CELL_GCM_TEXTURE_A1R5G5B5:
case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G6B5:
case CELL_GCM_TEXTURE_G8B8:
return get_subresources_layout_impl<1, u16>(pixels, w, h, depth, layer, texture.mipmap(), texture.pitch(), !is_swizzled);
return get_subresources_layout_impl<1, u16>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled);
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
return get_subresources_layout_impl<1, u64>(pixels, w, h, depth, layer, texture.mipmap(), texture.pitch(), !is_swizzled);
return get_subresources_layout_impl<1, u64>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled);
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
return get_subresources_layout_impl<4, u64>(pixels, w, h, depth, layer, texture.mipmap(), texture.pitch(), !is_swizzled);
return get_subresources_layout_impl<4, u64>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled);
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
return get_subresources_layout_impl<4, u128>(pixels, w, h, depth, layer, texture.mipmap(), texture.pitch(), !is_swizzled);
return get_subresources_layout_impl<4, u128>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled);
case CELL_GCM_TEXTURE_B8:
return get_subresources_layout_impl<1, u8>(pixels, w, h, depth, layer, texture.mipmap(), texture.pitch(), !is_swizzled);
return get_subresources_layout_impl<1, u8>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled);
}
throw EXCEPTION("Wrong format %d", format);
}
Expand Down
40 changes: 16 additions & 24 deletions rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,15 @@ namespace
const u8 format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
DXGI_FORMAT dxgi_format = get_texture_format(format);

if (texture.dimension() == rsx::texture_dimension::dimension1d)
switch (texture.get_extended_texture_dimension())
{
case rsx::texture_dimension_extended::texture_dimension_1d:
return CD3DX12_RESOURCE_DESC::Tex1D(dxgi_format, texture.width(), 1, texture.get_exact_mipmap_count());
}
else if (texture.dimension() == rsx::texture_dimension::dimension2d)
{
// if (texture.depth() < 2);
size_t depth = (texture.cubemap()) ? 6 : 1;
return CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, texture.width(), texture.height(), (UINT)depth, texture.get_exact_mipmap_count());
}
else if (texture.dimension() == rsx::texture_dimension::dimension3d)
{
case rsx::texture_dimension_extended::texture_dimension_2d:
return CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, texture.width(), texture.height(), 1, texture.get_exact_mipmap_count());
case rsx::texture_dimension_extended::texture_dimension_cubemap:
return CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, texture.width(), texture.height(), 6, texture.get_exact_mipmap_count());
case rsx::texture_dimension_extended::texture_dimension_3d:
return CD3DX12_RESOURCE_DESC::Tex3D(dxgi_format, texture.width(), texture.height(), texture.depth(), texture.get_exact_mipmap_count());
}
throw EXCEPTION("Unknow texture dimension");
Expand Down Expand Up @@ -146,31 +143,26 @@ ComPtr<ID3D12Resource> upload_single_texture(
D3D12_SHADER_RESOURCE_VIEW_DESC get_srv_descriptor_with_dimensions(const rsx::texture &tex)
{
D3D12_SHADER_RESOURCE_VIEW_DESC shared_resource_view_desc = {};
if (tex.dimension() == rsx::texture_dimension::dimension1d)
switch (tex.get_extended_texture_dimension())
{
case rsx::texture_dimension_extended::texture_dimension_1d:
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;
shared_resource_view_desc.Texture1D.MipLevels = tex.get_exact_mipmap_count();
return shared_resource_view_desc;
}
if (tex.dimension() == rsx::texture_dimension::dimension2d)
{
if (tex.cubemap())
{
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
shared_resource_view_desc.TextureCube.MipLevels = tex.get_exact_mipmap_count();
return shared_resource_view_desc;
}
case rsx::texture_dimension_extended::texture_dimension_2d:
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
shared_resource_view_desc.Texture2D.MipLevels = tex.get_exact_mipmap_count();
return shared_resource_view_desc;
}
if (tex.dimension() == rsx::texture_dimension::dimension3d)
{
case rsx::texture_dimension_extended::texture_dimension_cubemap:
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
shared_resource_view_desc.TextureCube.MipLevels = tex.get_exact_mipmap_count();
return shared_resource_view_desc;
case rsx::texture_dimension_extended::texture_dimension_3d:
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
shared_resource_view_desc.Texture3D.MipLevels = tex.get_exact_mipmap_count();
return shared_resource_view_desc;
}
throw EXCEPTION("Wrong texture dimension %d", tex.dimension());
throw EXCEPTION("Wrong texture dimension");
}
}

Expand Down
21 changes: 5 additions & 16 deletions rpcs3/Emu/RSX/RSXFragmentProgram.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include "GCM.h"
#include "RSXTexture.h"

enum
{
Expand Down Expand Up @@ -205,18 +206,6 @@ static const std::string rsx_fp_op_names[] =
"NULL", "BRK", "CAL", "IFE", "LOOP", "REP", "RET"
};


/**
* Use an extra cubemap format
*/
enum class texture_dimension_extended : u8
{
texture_dimension_1d = 0,
texture_dimension_2d = 1,
texture_dimension_cubemap = 2,
texture_dimension_3d = 3,
};

struct RSXFragmentProgram
{
u32 size;
Expand All @@ -234,15 +223,15 @@ struct RSXFragmentProgram
rsx::fog_mode fog_equation;
u16 height;

texture_dimension_extended get_texture_dimension(u8 id) const
rsx::texture_dimension_extended get_texture_dimension(u8 id) const
{
return (texture_dimension_extended)((texture_dimensions >> (id * 2)) & 0x3);
return (rsx::texture_dimension_extended)((texture_dimensions >> (id * 2)) & 0x3);
}

void set_texture_dimension(const std::array<texture_dimension_extended, 16> &dimensions)
void set_texture_dimension(const std::array<rsx::texture_dimension_extended, 16> &dimensions)
{
size_t id = 0;
for (const texture_dimension_extended &dim : dimensions)
for (const rsx::texture_dimension_extended &dim : dimensions)
{
texture_dimensions &= ~(0x3 << (id * 2));
u8 d = (u8)dim;
Expand Down
29 changes: 28 additions & 1 deletion rpcs3/Emu/RSX/RSXTexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,46 @@ namespace rsx
return rsx::to_texture_dimension((method_registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 4) & 0xf);
}

rsx::texture_dimension_extended texture::get_extended_texture_dimension() const
{
switch (dimension())
{
case rsx::texture_dimension::dimension1d: return rsx::texture_dimension_extended::texture_dimension_1d;
case rsx::texture_dimension::dimension3d: return rsx::texture_dimension_extended::texture_dimension_2d;
case rsx::texture_dimension::dimension2d: return cubemap() ? rsx::texture_dimension_extended::texture_dimension_cubemap : rsx::texture_dimension_extended::texture_dimension_2d;
}
}

u8 texture::format() const
{
return ((method_registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 8) & 0xff);
}

bool texture::is_compressed_format() const
{
int texture_format = format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
if (texture_format == CELL_GCM_TEXTURE_COMPRESSED_DXT1 ||
texture_format == CELL_GCM_TEXTURE_COMPRESSED_DXT23 ||
texture_format == CELL_GCM_TEXTURE_COMPRESSED_DXT45)
return true;
return false;
}

u16 texture::mipmap() const
{
return ((method_registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 16) & 0xffff);
}

u16 texture::get_exact_mipmap_count() const
{
u16 max_mipmap_count = static_cast<u16>(floor(log2(std::max(width(), height()))) + 1);
if (is_compressed_format())
{
// OpenGL considers that highest mipmap level for DXTC format is when either width or height is 1
// not both. Assume it's the same for others backend.
u16 max_mipmap_count = static_cast<u16>(floor(log2(std::min(width() / 4, height() / 4))) + 1);
return std::min(mipmap(), max_mipmap_count);
}
u16 max_mipmap_count = static_cast<u16>(floor(log2(std::max(width(), height()))) + 1) - 2;
return std::min(mipmap(), max_mipmap_count);
}

Expand Down
18 changes: 18 additions & 0 deletions rpcs3/Emu/RSX/RSXTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@

namespace rsx
{
/**
* Use an extra cubemap format
*/
enum class texture_dimension_extended : u8
{
texture_dimension_1d = 0,
texture_dimension_2d = 1,
texture_dimension_cubemap = 2,
texture_dimension_3d = 3,
};

class texture
{
protected:
Expand All @@ -20,7 +31,14 @@ namespace rsx
bool cubemap() const;
u8 border_type() const;
rsx::texture_dimension dimension() const;
/**
* 2d texture can be either plane or cubemap texture depending on cubemap bit.
* Since cubemap is a format per se in all gfx API this function directly returns
* cubemap as a separate dimension.
*/
rsx::texture_dimension_extended get_extended_texture_dimension() const;
u8 format() const;
bool is_compressed_format() const;
u16 mipmap() const;
/**
* mipmap() returns value from register which can be higher than the actual number of mipmap level.
Expand Down
13 changes: 1 addition & 12 deletions rpcs3/Emu/RSX/RSXThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -724,19 +724,8 @@ namespace rsx
{
if (!textures[i].enabled())
texture_dimensions[i] = texture_dimension_extended::texture_dimension_2d;
else if (textures[i].dimension() == rsx::texture_dimension::dimension1d)
texture_dimensions[i] = texture_dimension_extended::texture_dimension_1d;
else if (textures[i].dimension() == rsx::texture_dimension::dimension2d)
{
if (textures[i].cubemap())
texture_dimensions[i] = texture_dimension_extended::texture_dimension_cubemap;
else
texture_dimensions[i] = texture_dimension_extended::texture_dimension_2d;
}
else if (textures[i].dimension() == rsx::texture_dimension::dimension3d)
texture_dimensions[i] = texture_dimension_extended::texture_dimension_3d;
else
throw EXCEPTION("Unable to determine texture dimension");
texture_dimensions[i] = textures[i].get_extended_texture_dimension();
if (textures[i].enabled() && (textures[i].format() & CELL_GCM_TEXTURE_UN))
result.unnormalized_coords |= (1 << i);
}
Expand Down