Integrated to Software Rasterizer

This commit is contained in:
Fernando Sahmkow 2017-01-18 14:24:42 -05:00
parent bed6207ac7
commit 230dfc5f74
11 changed files with 284 additions and 54 deletions

View File

@ -110,6 +110,12 @@ inline const Math::Vec4<u8> DecodeRGBA4(const u8* bytes) {
Convert4To8((pixel >> 4) & 0xF), Convert4To8(pixel & 0xF)};
}
// would an specialization but currently, you can't specialize static members.
inline const Math::Vec4<u8> DecodeTexel(unsigned int rgba) {
return {(u8)(rgba & 0x00FF), (u8)((rgba >> 8) & 0x00FF), (u8)((rgba >> 16) & 0x00FF),
(u8)((rgba >> 24) & 0x00FF)};
}
/**
* Decode a depth value stored in D16 format
* @param bytes Pointer to encoded source value

View File

@ -21,6 +21,8 @@
#include "video_core/pica_types.h"
#include "video_core/rasterizer.h"
#include "video_core/shader/shader.h"
#include "video_core/texture/codec.h"
#include "video_core/texture/formats.h"
#include "video_core/utils.h"
namespace Pica {
@ -399,6 +401,25 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0, const Shader
auto textures = regs.GetTextures();
auto tev_stages = regs.GetTevStages();
std::unique_ptr<u8[]> decoded_textures[3];
for (int i = 0; i < 3; i++) {
const auto& texture = textures[i];
if (!texture.enabled)
continue;
u8* texture_data = Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress());
auto format = Pica::Texture::Format::FromTextureFormat(texture.format);
auto tmp = Pica::Texture::CodecFactory::build(format, texture_data, texture.config.width,
texture.config.height);
Pica::Texture::Codec* codec = tmp.get();
codec->configTiling(true, 8);
codec->configRGBATransform(true);
codec->validate();
if (!codec->invalid()) {
codec->decode();
decoded_textures[i] = codec->transferInternalBuffer();
}
}
bool stencil_action_enable = g_state.regs.output_merger.stencil_test.enable &&
g_state.regs.framebuffer.depth_format == Regs::DepthFormat::D24S8;
const auto stencil_test = g_state.regs.output_merger.stencil_test;
@ -573,17 +594,17 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0, const Shader
// NOTE: This may not be the right place for the inversion.
// TODO: Check if this applies to ETC textures, too.
s = GetWrappedTexCoord(texture.config.wrap_s, s, texture.config.width);
t = texture.config.height - 1 -
GetWrappedTexCoord(texture.config.wrap_t, t, texture.config.height);
t = GetWrappedTexCoord(texture.config.wrap_t, t, texture.config.height);
u8* decoded_texture = decoded_textures[i].get();
u64 pos = s + texture.config.width * t;
u32 texel;
std::memcpy(&texel, &decoded_texture[pos * 4], 4);
// TODO: Apply the min and mag filters to the texture
texture_color[i] = Color::DecodeTexel(texel);
#if PICA_DUMP_TEXTURES
u8* texture_data =
Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress());
auto info =
DebugUtils::TextureInfo::FromPicaRegister(texture.config, texture.format);
// TODO: Apply the min and mag filters to the texture
texture_color[i] = DebugUtils::LookupTexture(texture_data, s, t, info);
#if PICA_DUMP_TEXTURES
DebugUtils::DumpTexture(texture.config, texture_data);
#endif
}
@ -958,8 +979,9 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0, const Shader
u8 new_stencil =
PerformStencilAction(action, old_stencil, stencil_test.reference_value);
if (g_state.regs.framebuffer.allow_depth_stencil_write != 0)
SetStencil(x >> 4, y >> 4, (new_stencil & stencil_test.write_mask) |
(old_stencil & ~stencil_test.write_mask));
SetStencil(x >> 4, y >> 4,
(new_stencil & stencil_test.write_mask) |
(old_stencil & ~stencil_test.write_mask));
};
if (stencil_action_enable) {

View File

@ -17,7 +17,6 @@
#include "common/vector_math.h"
#include "core/frontend/emu_window.h"
#include "core/memory.h"
#include "video_core/debug_utils/debug_utils.h"
#include "video_core/pica_state.h"
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_state.h"
@ -461,8 +460,7 @@ CachedSurface* RasterizerCacheOpenGL::GetSurfaceRect(const CachedSurface& params
CachedSurface* RasterizerCacheOpenGL::GetTextureSurface(
const Pica::Regs::FullTextureConfig& config) {
Pica::DebugUtils::TextureInfo info =
Pica::DebugUtils::TextureInfo::FromPicaRegister(config.config, config.format);
Pica::Texture::Info info = Pica::Texture::Info::FromPicaRegister(config.config, config.format);
CachedSurface params;
params.addr = info.physical_address;

View File

@ -1,3 +1,6 @@
#include <cstring>
#include <memory>
#include <utility>
#include "common/color.h"
#include "common/math_util.h"
#include "common/swap.h"
@ -110,6 +113,30 @@ inline void Codec::encode_morton_pass() {
this->start_nibbles_size * 4);
}
u32 Codec::getTexel(u32 x, u32 y) {
const u32 tiling = this->morton_pass_tiling;
const u8* position = this->getTile(x, y);
const u32 bpp = this->start_nibbles_size * 4; // bits per pixel
const u32 mask = 0x0000FFFFFFFFUL >> (32 - bpp);
const u32 bit = (bpp % 8);
const u64 offset = (u64)EncodeMorton(x % tiling, y % tiling) % (tiling * tiling);
u32 result;
const u32 read_size = (bpp / 8) | ((bpp < 8) & 0x01);
std::memcpy(&result, &position[offset], read_size);
result >>= bit;
result &= mask;
return result;
}
u8* Codec::getTile(u32 x, u32 y) {
const u32 tiling = this->morton_pass_tiling;
x = (x / tiling) * tiling;
y = (y / tiling) * tiling;
const u32 bpp = this->start_nibbles_size * 4;
const u64 offset = ((x + y * this->width) * bpp) / 8;
return (this->target_buffer + offset);
}
std::unique_ptr<Codec> CodecFactory::build(Format::Type format, u8* target, u32 width, u32 height) {
switch (format) {
case Format::Type::RGBA8:

View File

@ -4,6 +4,7 @@
#include <iostream>
#include <memory>
#include "common/common_types.h"
#include "common/vector_math.h"
#include "video_core/texture/formats.h"
namespace Pica {
@ -23,6 +24,11 @@ public:
virtual void decode();
virtual void encode();
// for legacy code compatibility
// returns the corresponding texel in RGBA format.
// prefer full decode/encode than texel lookups for full image decoding.
virtual const Math::Vec4<u8> lookupTexel(u32 x, u32 y) = 0;
inline void setWidth(u32 width) {
this->width = width;
}
@ -56,8 +62,6 @@ protected:
u32 morton_pass_tiling = 8;
bool raw_RGBA = false;
bool preconverted = false;
bool disable_components = false;
u32 disable_components_mask = 0;
u32 start_nibbles_size;
u32 expected_nibbles_size;
@ -77,6 +81,8 @@ protected:
inline void decode_morton_pass();
inline void encode_morton_pass();
u32 getTexel(u32 x, u32 y);
u8* getTile(u32 x, u32 y);
};
namespace CodecFactory {

View File

@ -10,6 +10,25 @@ namespace Pica {
namespace Texture {
struct Info {
PAddr physical_address;
int width;
int height;
int stride;
Pica::Regs::TextureFormat format;
static Info FromPicaRegister(const Pica::Regs::TextureConfig& config,
const Pica::Regs::TextureFormat& format) {
Info info;
info.physical_address = config.GetPhysicalAddress();
info.width = config.width;
info.height = config.height;
info.format = format;
info.stride = Pica::Regs::NibblesPerPixel(info.format) * info.width / 2;
return info;
}
};
struct Format {
enum class Type {
@ -92,17 +111,6 @@ struct Format {
}; // Format
struct Info {
PAddr physical_address;
int width;
int height;
int stride;
Pica::Regs::TextureFormat format;
static Info FromPicaRegister(const Pica::Regs::TextureConfig& config,
const Pica::Regs::TextureFormat& format);
};
} // Texture
} // Pica

View File

@ -1,8 +1,10 @@
#include "common/color.h"
#include "common/common_types.h"
#include "common/vector_math.h"
#include "video_core/texture/internal/codecs.h"
#include "video_core/texture/internal/etc1.h"
#include "video_core/texture/internal/morton.h"
#include "video_core/texture/internal/texture_utils.h"
///////////////////////////////////////////////////////////////////////////////
// Optimizations
//////////////////////////////////////////////////////////////////////////////
@ -20,3 +22,6 @@
// Encoders
#include "encoders.cpp"
// Lookup Texture
#include "lookup.cpp"

View File

@ -4,15 +4,19 @@
#include <iostream>
#include <memory>
#include "common/common_types.h"
#include "common/vector_math.h"
#include "video_core/texture/codec.h"
#include "video_core/texture/formats.h"
// each texture format codec
class RGBACodec : public Pica::Texture::Codec {
public:
RGBACodec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
RGBACodec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -26,9 +30,12 @@ protected:
class RGBCodec : public Pica::Texture::Codec {
public:
RGBCodec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
RGBCodec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -42,9 +49,12 @@ protected:
class RGB5A1Codec : public Pica::Texture::Codec {
public:
RGB5A1Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
RGB5A1Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -58,9 +68,12 @@ protected:
class RGBA4Codec : public Pica::Texture::Codec {
public:
RGBA4Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
RGBA4Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -74,9 +87,12 @@ protected:
class RGB565Codec : public Pica::Texture::Codec {
public:
RGB565Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
RGB565Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -90,9 +106,12 @@ protected:
class RG8Codec : public Pica::Texture::Codec {
public:
RG8Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
RG8Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -106,9 +125,12 @@ protected:
class IA8Codec : public Pica::Texture::Codec {
public:
IA8Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
IA8Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -122,9 +144,12 @@ protected:
class I8Codec : public Pica::Texture::Codec {
public:
I8Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
I8Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -138,9 +163,12 @@ protected:
class A8Codec : public Pica::Texture::Codec {
public:
A8Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
A8Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -154,9 +182,12 @@ protected:
class IA4Codec : public Pica::Texture::Codec {
public:
IA4Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
IA4Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -170,9 +201,12 @@ protected:
class I4Codec : public Pica::Texture::Codec {
public:
I4Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
I4Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -186,9 +220,12 @@ protected:
class A4Codec : public Pica::Texture::Codec {
public:
A4Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
A4Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -202,9 +239,12 @@ protected:
class ETC1Codec : public Pica::Texture::Codec {
public:
ETC1Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
ETC1Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -218,9 +258,12 @@ protected:
class ETC1A4Codec : public Pica::Texture::Codec {
public:
ETC1A4Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
ETC1A4Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -234,9 +277,12 @@ protected:
class D16Codec : public Pica::Texture::Codec {
public:
D16Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
D16Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -250,9 +296,12 @@ protected:
class D24Codec : public Pica::Texture::Codec {
public:
D24Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
D24Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {
@ -266,9 +315,12 @@ protected:
class D24S8Codec : public Pica::Texture::Codec {
public:
D24S8Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {}
D24S8Codec(u8* target, u32 width, u32 height) : Pica::Texture::Codec(target, width, height) {
this->setSize();
}
void decode();
void encode();
const Math::Vec4<u8> lookupTexel(u32 x, u32 y);
protected:
virtual void setSize() {

View File

@ -0,0 +1,110 @@
const Math::Vec4<u8> RGBACodec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
u8* tmp = reinterpret_cast<u8*>(&texel);
return Color::DecodeRGBA8(tmp);
}
const Math::Vec4<u8> RGBCodec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
u8* tmp = reinterpret_cast<u8*>(&texel);
return Color::DecodeRGB8(tmp);
}
const Math::Vec4<u8> RGB5A1Codec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
u8* tmp = reinterpret_cast<u8*>(&texel);
return Color::DecodeRGB5A1(tmp);
}
const Math::Vec4<u8> RGB565Codec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
u8* tmp = reinterpret_cast<u8*>(&texel);
return Color::DecodeRGB565(tmp);
}
const Math::Vec4<u8> RGBA4Codec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
u8* tmp = reinterpret_cast<u8*>(&texel);
return Color::DecodeRGBA4(tmp);
}
const Math::Vec4<u8> RG8Codec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
u8* tmp = reinterpret_cast<u8*>(&texel);
return Color::DecodeRG8(tmp);
}
const Math::Vec4<u8> IA8Codec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
u8 intensity = (texel & 0x00FF00) >> 8;
u8 alpha = (texel & 0x0000FF);
Math::Vec4<u8> result(intensity, intensity, intensity, alpha);
return result;
}
const Math::Vec4<u8> IA4Codec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
u8 intensity = Color::Convert4To8((texel & 0x00F0) >> 4);
u8 alpha = Color::Convert4To8(texel & 0x0F);
Math::Vec4<u8> result(intensity, intensity, intensity, alpha);
return result;
}
const Math::Vec4<u8> I8Codec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
u8 intensity = (texel & 0x0000FF);
Math::Vec4<u8> result(intensity, intensity, intensity, 255);
return result;
}
const Math::Vec4<u8> I4Codec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
const u32 bit = 1 - (x % 2);
u8 intensity = Color::Convert4To8((texel & 0x0000FF) >> bit);
Math::Vec4<u8> result(intensity, intensity, intensity, 255);
return result;
}
const Math::Vec4<u8> A8Codec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
u8 alpha = (texel & 0x0000FF);
Math::Vec4<u8> result(0, 0, 0, alpha);
return result;
}
const Math::Vec4<u8> A4Codec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
const u32 bit = 1 - (x % 2);
u8 alpha = Color::Convert4To8((texel & 0x0000FF) >> bit);
Math::Vec4<u8> result(0, 0, 0, alpha);
return result;
}
const Math::Vec4<u8> ETC1Codec::lookupTexel(u32 x, u32 y) {
Math::Vec4<u8> result(0, 0, 0, 255);
return result;
}
const Math::Vec4<u8> ETC1A4Codec::lookupTexel(u32 x, u32 y) {
Math::Vec4<u8> result(0, 0, 0, 255);
return result;
}
const Math::Vec4<u8> D16Codec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
u8* tmp = reinterpret_cast<u8*>(&texel);
return Color::DecodeRG8(tmp);
}
const Math::Vec4<u8> D24Codec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
u8* tmp = reinterpret_cast<u8*>(&texel);
return Color::DecodeRGB8(tmp);
}
const Math::Vec4<u8> D24S8Codec::lookupTexel(u32 x, u32 y) {
u32 texel = super::getTexel(x, y);
u8* tmp = reinterpret_cast<u8*>(&texel);
return Color::DecodeRGBA8(tmp);
}

View File

@ -19,22 +19,16 @@ static u32 Compact1By1(u32 x) {
return x;
}
static u32 EncodeMorton(u32 x, u32 y) {
u32 EncodeMorton(u32 x, u32 y) {
return (Part1By1(y) << 1) | Part1By1(x);
}
static u32 DecodeMortonX(u32 code) {
u32 DecodeMortonX(u32 code) {
return Compact1By1(code >> 0);
}
static u32 DecodeMortonY(u32 code) {
u32 DecodeMortonY(u32 code) {
return Compact1By1(code >> 1);
}
u32 MortonOffset(u32 x, u32 y, u32 width, u32 height, u32 tiling, u32 bpp) {
u32 tile = (x + y * height) * width / (tiling * tiling);
tile = (tile * bpp) / 8;
return tile + EncodeMorton(x % tiling, y % tiling);
}
#include "morton8x8_optimized.cpp"

View File

@ -2,7 +2,9 @@
#include "common/common_types.h"
u32 MortonOffset(u32 x, u32 y, u32 width, u32 height, u32 tiling, u32 bpp);
u32 EncodeMorton(u32 x, u32 y);
u32 DecodeMortonX(u32 code);
u32 DecodeMortonY(u32 code);
namespace Decoders {
bool Morton_8x8(u8* morton_buffer, u8* matrix_buffer, u32 width, u32 height, u32 bpp);