Compare commits

...

5 Commits

Author SHA1 Message Date
FernandoS27
f5379ac07e Fix cubemaps to use a less hacky method of loading 2018-10-16 19:49:02 -04:00
FernandoS27
5a15af013d Clang format and other fixes 2018-10-16 18:17:50 -04:00
FernandoS27
01db162f81 Implement Reinterpret Surface, to accurately blit 3D textures 2018-10-16 18:14:06 -04:00
FernandoS27
7d5e6b84fc Implement GetInRange in the Rasterizer Cache 2018-10-16 18:11:06 -04:00
FernandoS27
ee536c3ac2 Implement 3D Textures 2018-10-16 18:11:04 -04:00
4 changed files with 33 additions and 39 deletions

View File

@@ -448,7 +448,10 @@ public:
BitField<8, 3, u32> block_depth;
BitField<12, 1, InvMemoryLayout> type;
} memory_layout;
u32 array_mode;
union {
BitField<0, 16, u32> array_mode;
BitField<16, 1, u32> volume;
};
u32 layer_stride;
u32 base_layer;
INSERT_PADDING_WORDS(7);

View File

@@ -155,6 +155,7 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {
params.rt.index = static_cast<u32>(index);
params.rt.array_mode = config.array_mode;
params.rt.layer_stride = config.layer_stride;
params.rt.volume = config.volume;
params.rt.base_layer = config.base_layer;
params.InitCacheParameters(config.Address());
@@ -895,9 +896,26 @@ void CachedSurface::LoadGLBuffer() {
block_depth = 1U;
}
morton_to_gl_fns[static_cast<std::size_t>(params.pixel_format)](
params.width, params.block_height, params.height, block_depth, depth, gl_buffer.data(),
gl_buffer.size(), params.addr);
if (params.target == SurfaceParams::SurfaceTarget::TextureCubemap) {
// TODO(Blinkhawk): Figure where this number comes from and if it's constant or depends
// on the objects size and/or address.
u64 magic_number = 0x6000;
u64 offset = 0;
u64 offset_gl = 0;
u64 size = params.SizeInBytesCubeFace();
u64 gl_size = params.SizeInBytesCubeFaceGL();
for (u32 i = 0; i < depth; i++) {
morton_to_gl_fns[static_cast<std::size_t>(params.pixel_format)](
params.width, params.block_height, params.height, block_depth, 1,
gl_buffer.data() + offset_gl, gl_size, params.addr + offset);
offset += size + magic_number;
offset_gl += gl_size;
}
} else {
morton_to_gl_fns[static_cast<std::size_t>(params.pixel_format)](
params.width, params.block_height, params.height, block_depth, depth,
gl_buffer.data(), gl_buffer.size(), params.addr);
}
} else {
const auto texture_src_data{Memory::GetPointer(params.addr)};
const auto texture_src_data_end{texture_src_data + params.size_in_bytes_gl};
@@ -1126,8 +1144,8 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, bool pres
} else if (preserve_contents) {
// If surface parameters changed and we care about keeping the previous data, recreate
// the surface from the old one
Unregister(surface);
Surface new_surface{RecreateSurface(surface, params)};
Unregister(surface);
Register(new_surface);
return new_surface;
} else {
@@ -1224,41 +1242,10 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,
CopySurface(old_surface, new_surface, copy_pbo.handle);
}
break;
case SurfaceParams::SurfaceTarget::TextureCubemap: {
if (old_params.rt.array_mode != 1) {
// TODO(bunnei): This is used by Breath of the Wild, I'm not sure how to implement this
// yet (array rendering used as a cubemap texture).
LOG_CRITICAL(HW_GPU, "Unhandled rendertarget array_mode {}", old_params.rt.array_mode);
UNREACHABLE();
return new_surface;
}
// This seems to be used for render-to-cubemap texture
ASSERT_MSG(old_params.target == SurfaceParams::SurfaceTarget::Texture2D, "Unexpected");
ASSERT_MSG(old_params.pixel_format == new_params.pixel_format, "Unexpected");
ASSERT_MSG(old_params.rt.base_layer == 0, "Unimplemented");
// TODO(bunnei): Verify the below - this stride seems to be in 32-bit words, not pixels.
// Tested with Splatoon 2, Super Mario Odyssey, and Breath of the Wild.
const std::size_t byte_stride{old_params.rt.layer_stride * sizeof(u32)};
for (std::size_t index = 0; index < new_params.depth; ++index) {
Surface face_surface{TryGetReservedSurface(old_params)};
ASSERT_MSG(face_surface, "Unexpected");
if (is_blit) {
BlitSurface(face_surface, new_surface, read_framebuffer.handle,
draw_framebuffer.handle, face_surface->GetSurfaceParams().rt.index,
new_params.rt.index, index);
} else {
CopySurface(face_surface, new_surface, copy_pbo.handle,
face_surface->GetSurfaceParams().rt.index, new_params.rt.index, index);
}
old_params.addr += byte_stride;
}
case SurfaceParams::SurfaceTarget::TextureCubemap:
case SurfaceParams::SurfaceTarget::Texture3D:
AccurateCopySurface(old_surface, new_surface);
break;
}
default:
LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
static_cast<u32>(new_params.target));

View File

@@ -132,6 +132,8 @@ struct SurfaceParams {
case Tegra::Texture::TextureType::Texture2D:
case Tegra::Texture::TextureType::Texture2DNoMipmap:
return SurfaceTarget::Texture2D;
case Tegra::Texture::TextureType::Texture3D:
return SurfaceTarget::Texture3D;
case Tegra::Texture::TextureType::TextureCubemap:
return SurfaceTarget::TextureCubemap;
case Tegra::Texture::TextureType::Texture1DArray:
@@ -791,6 +793,7 @@ struct SurfaceParams {
struct {
u32 index;
u32 array_mode;
u32 volume;
u32 layer_stride;
u32 base_layer;
} rt;

View File

@@ -1142,6 +1142,7 @@ private:
case Tegra::Shader::TextureType::Texture2D: {
return 2;
}
case Tegra::Shader::TextureType::Texture3D:
case Tegra::Shader::TextureType::TextureCube: {
return 3;
}