gl_rasterizer_cache: Keep track of texture type per surface.
This commit is contained in:
parent
a439f7b6e1
commit
030676b95d
3 changed files with 84 additions and 32 deletions
|
@ -700,6 +700,7 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
|
||||||
Surface surface = res_cache.GetTextureSurface(texture);
|
Surface surface = res_cache.GetTextureSurface(texture);
|
||||||
if (surface != nullptr) {
|
if (surface != nullptr) {
|
||||||
state.texture_units[current_bindpoint].texture = surface->Texture().handle;
|
state.texture_units[current_bindpoint].texture = surface->Texture().handle;
|
||||||
|
state.texture_units[current_bindpoint].target = surface->Target();
|
||||||
state.texture_units[current_bindpoint].swizzle.r =
|
state.texture_units[current_bindpoint].swizzle.r =
|
||||||
MaxwellToGL::SwizzleSource(texture.tic.x_source);
|
MaxwellToGL::SwizzleSource(texture.tic.x_source);
|
||||||
state.texture_units[current_bindpoint].swizzle.g =
|
state.texture_units[current_bindpoint].swizzle.g =
|
||||||
|
|
|
@ -55,6 +55,7 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
|
||||||
params.size_in_bytes = params.SizeInBytes();
|
params.size_in_bytes = params.SizeInBytes();
|
||||||
params.cache_width = Common::AlignUp(params.width, 16);
|
params.cache_width = Common::AlignUp(params.width, 16);
|
||||||
params.cache_height = Common::AlignUp(params.height, 16);
|
params.cache_height = Common::AlignUp(params.height, 16);
|
||||||
|
params.target = SurfaceTargetFromTextureType(config.tic.texture_type);
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +74,7 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
|
||||||
params.size_in_bytes = params.SizeInBytes();
|
params.size_in_bytes = params.SizeInBytes();
|
||||||
params.cache_width = Common::AlignUp(params.width, 16);
|
params.cache_width = Common::AlignUp(params.width, 16);
|
||||||
params.cache_height = Common::AlignUp(params.height, 16);
|
params.cache_height = Common::AlignUp(params.height, 16);
|
||||||
|
params.target = SurfaceTarget::Texture2D;
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +95,7 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
|
||||||
params.size_in_bytes = params.SizeInBytes();
|
params.size_in_bytes = params.SizeInBytes();
|
||||||
params.cache_width = Common::AlignUp(params.width, 16);
|
params.cache_width = Common::AlignUp(params.width, 16);
|
||||||
params.cache_height = Common::AlignUp(params.height, 16);
|
params.cache_height = Common::AlignUp(params.height, 16);
|
||||||
|
params.target = SurfaceTarget::Texture2D;
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +169,26 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
|
||||||
ComponentType::Float, false}, // Z32FS8
|
ComponentType::Float, false}, // Z32FS8
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
static GLenum SurfaceTargetToGL(SurfaceParams::SurfaceTarget target) {
|
||||||
|
switch (target) {
|
||||||
|
case SurfaceParams::SurfaceTarget::Texture1D:
|
||||||
|
return GL_TEXTURE_1D;
|
||||||
|
case SurfaceParams::SurfaceTarget::Texture2D:
|
||||||
|
return GL_TEXTURE_2D;
|
||||||
|
case SurfaceParams::SurfaceTarget::Texture3D:
|
||||||
|
return GL_TEXTURE_3D;
|
||||||
|
case SurfaceParams::SurfaceTarget::Texture1DArray:
|
||||||
|
return GL_TEXTURE_1D_ARRAY;
|
||||||
|
case SurfaceParams::SurfaceTarget::Texture2DArray:
|
||||||
|
return GL_TEXTURE_2D_ARRAY;
|
||||||
|
case SurfaceParams::SurfaceTarget::TextureCubemap:
|
||||||
|
return GL_TEXTURE_CUBE_MAP;
|
||||||
|
}
|
||||||
|
LOG_CRITICAL(Render_OpenGL, "Unimplemented texture target={}", static_cast<u32>(target));
|
||||||
|
UNREACHABLE();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
|
static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
|
||||||
ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size());
|
ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size());
|
||||||
auto& format = tex_format_tuples[static_cast<unsigned int>(pixel_format)];
|
auto& format = tex_format_tuples[static_cast<unsigned int>(pixel_format)];
|
||||||
|
@ -357,33 +380,6 @@ static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, VAddr),
|
||||||
// clang-format on
|
// clang-format on
|
||||||
};
|
};
|
||||||
|
|
||||||
// Allocate an uninitialized texture of appropriate size and format for the surface
|
|
||||||
static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tuple, u32 width,
|
|
||||||
u32 height) {
|
|
||||||
OpenGLState cur_state = OpenGLState::GetCurState();
|
|
||||||
|
|
||||||
// Keep track of previous texture bindings
|
|
||||||
GLuint old_tex = cur_state.texture_units[0].texture;
|
|
||||||
cur_state.texture_units[0].texture = texture;
|
|
||||||
cur_state.Apply();
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
|
|
||||||
if (!format_tuple.compressed) {
|
|
||||||
// Only pre-create the texture for non-compressed textures.
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, width, height, 0,
|
|
||||||
format_tuple.format, format_tuple.type, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
// Restore previous texture bindings
|
|
||||||
cur_state.texture_units[0].texture = old_tex;
|
|
||||||
cur_state.Apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, GLuint dst_tex,
|
static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, GLuint dst_tex,
|
||||||
const MathUtil::Rectangle<u32>& dst_rect, SurfaceType type,
|
const MathUtil::Rectangle<u32>& dst_rect, SurfaceType type,
|
||||||
GLuint read_fb_handle, GLuint draw_fb_handle) {
|
GLuint read_fb_handle, GLuint draw_fb_handle) {
|
||||||
|
@ -438,12 +434,34 @@ static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rec
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedSurface::CachedSurface(const SurfaceParams& params) : params(params) {
|
CachedSurface::CachedSurface(const SurfaceParams& params)
|
||||||
|
: params(params), gl_target(SurfaceTargetToGL(params.target)) {
|
||||||
texture.Create();
|
texture.Create();
|
||||||
const auto& rect{params.GetRect()};
|
const auto& rect{params.GetRect()};
|
||||||
AllocateSurfaceTexture(texture.handle,
|
|
||||||
GetFormatTuple(params.pixel_format, params.component_type),
|
OpenGLState cur_state = OpenGLState::GetCurState();
|
||||||
rect.GetWidth(), rect.GetHeight());
|
|
||||||
|
// Keep track of previous texture bindings
|
||||||
|
GLuint old_tex = cur_state.texture_units[0].texture;
|
||||||
|
cur_state.texture_units[0].texture = texture.handle;
|
||||||
|
cur_state.Apply();
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type);
|
||||||
|
if (!format_tuple.compressed) {
|
||||||
|
// Only pre-create the texture for non-compressed textures.
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, rect.GetWidth(),
|
||||||
|
rect.GetHeight(), 0, format_tuple.format, format_tuple.type, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
// Restore previous texture bindings
|
||||||
|
cur_state.texture_units[0].texture = old_tex;
|
||||||
|
cur_state.Apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) {
|
static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) {
|
||||||
|
|
|
@ -109,6 +109,33 @@ struct SurfaceParams {
|
||||||
Invalid = 4,
|
Invalid = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class SurfaceTarget {
|
||||||
|
Texture1D,
|
||||||
|
Texture2D,
|
||||||
|
Texture3D,
|
||||||
|
Texture1DArray,
|
||||||
|
Texture2DArray,
|
||||||
|
TextureCubemap,
|
||||||
|
};
|
||||||
|
|
||||||
|
static SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type) {
|
||||||
|
switch (texture_type) {
|
||||||
|
case Tegra::Texture::TextureType::Texture1D:
|
||||||
|
return SurfaceTarget::Texture1D;
|
||||||
|
case Tegra::Texture::TextureType::Texture2D:
|
||||||
|
case Tegra::Texture::TextureType::Texture2DNoMipmap:
|
||||||
|
return SurfaceTarget::Texture2D;
|
||||||
|
case Tegra::Texture::TextureType::Texture1DArray:
|
||||||
|
return SurfaceTarget::Texture1DArray;
|
||||||
|
case Tegra::Texture::TextureType::Texture2DArray:
|
||||||
|
return SurfaceTarget::Texture2DArray;
|
||||||
|
default:
|
||||||
|
LOG_CRITICAL(HW_GPU, "Unimplemented texture_type={}", static_cast<u32>(texture_type));
|
||||||
|
UNREACHABLE();
|
||||||
|
return SurfaceTarget::Texture2D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the compression factor for the specified PixelFormat. This applies to just the
|
* Gets the compression factor for the specified PixelFormat. This applies to just the
|
||||||
* "compressed width" and "compressed height", not the overall compression factor of a
|
* "compressed width" and "compressed height", not the overall compression factor of a
|
||||||
|
@ -666,6 +693,7 @@ struct SurfaceParams {
|
||||||
u32 height;
|
u32 height;
|
||||||
u32 unaligned_height;
|
u32 unaligned_height;
|
||||||
size_t size_in_bytes;
|
size_t size_in_bytes;
|
||||||
|
SurfaceTarget target;
|
||||||
|
|
||||||
// Parameters used for caching only
|
// Parameters used for caching only
|
||||||
u32 cache_width;
|
u32 cache_width;
|
||||||
|
@ -709,6 +737,10 @@ public:
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum Target() const {
|
||||||
|
return gl_target;
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr unsigned int GetGLBytesPerPixel(SurfaceParams::PixelFormat format) {
|
static constexpr unsigned int GetGLBytesPerPixel(SurfaceParams::PixelFormat format) {
|
||||||
if (format == SurfaceParams::PixelFormat::Invalid)
|
if (format == SurfaceParams::PixelFormat::Invalid)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -724,13 +756,14 @@ public:
|
||||||
void LoadGLBuffer();
|
void LoadGLBuffer();
|
||||||
void FlushGLBuffer();
|
void FlushGLBuffer();
|
||||||
|
|
||||||
// Upload/Download data in gl_buffer in/to this surface's texture
|
// Upload data in gl_buffer to this surface's texture
|
||||||
void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle);
|
void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OGLTexture texture;
|
OGLTexture texture;
|
||||||
std::vector<u8> gl_buffer;
|
std::vector<u8> gl_buffer;
|
||||||
SurfaceParams params;
|
SurfaceParams params;
|
||||||
|
GLenum gl_target;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {
|
class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {
|
||||||
|
|
Loading…
Reference in a new issue