video_core: Cleanup surface interface

* Remove unused FramebufferView and make the opengl handles private
This commit is contained in:
GPUCode
2023-02-15 15:38:49 +02:00
parent c7d315058e
commit e67a4a739a
6 changed files with 67 additions and 111 deletions

View File

@ -40,14 +40,14 @@ void D24S8toRGBA8::Reinterpret(const Surface& source, VideoCore::Rect2D src_rect
SCOPE_EXIT({ prev_state.Apply(); }); SCOPE_EXIT({ prev_state.Apply(); });
OpenGLState state; OpenGLState state;
state.texture_units[0].texture_2d = source.texture.handle; state.texture_units[0].texture_2d = source.Handle();
// Use glTextureView on desktop to avoid intermediate copy // Use glTextureView on desktop to avoid intermediate copy
if (use_texture_view) { if (use_texture_view) {
temp_tex.Create(); temp_tex.Create();
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glTextureView(temp_tex.handle, GL_TEXTURE_2D, source.texture.handle, GL_DEPTH24_STENCIL8, 0, glTextureView(temp_tex.handle, GL_TEXTURE_2D, source.Handle(), GL_DEPTH24_STENCIL8, 0, 1, 0,
1, 0, 1); 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
} else { } else {
@ -66,12 +66,12 @@ void D24S8toRGBA8::Reinterpret(const Surface& source, VideoCore::Rect2D src_rect
state.draw.shader_program = program.handle; state.draw.shader_program = program.handle;
state.Apply(); state.Apply();
glBindImageTexture(2, dest.texture.handle, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); glBindImageTexture(2, dest.Handle(), 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
if (!use_texture_view) { if (!use_texture_view) {
glCopyImageSubData(source.texture.handle, GL_TEXTURE_2D, 0, src_rect.left, src_rect.bottom, glCopyImageSubData(source.Handle(), GL_TEXTURE_2D, 0, src_rect.left, src_rect.bottom, 0,
0, temp_tex.handle, GL_TEXTURE_2D, 0, src_rect.left, src_rect.bottom, 0, temp_tex.handle, GL_TEXTURE_2D, 0, src_rect.left, src_rect.bottom, 0,
src_rect.GetWidth(), src_rect.GetHeight(), 1); src_rect.GetWidth(), src_rect.GetHeight(), 1);
} }
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
@ -143,7 +143,7 @@ void RGBA4toRGB5A1::Reinterpret(const Surface& source, VideoCore::Rect2D src_rec
SCOPE_EXIT({ prev_state.Apply(); }); SCOPE_EXIT({ prev_state.Apply(); });
OpenGLState state; OpenGLState state;
state.texture_units[0].texture_2d = source.texture.handle; state.texture_units[0].texture_2d = source.Handle();
state.draw.draw_framebuffer = draw_fbo.handle; state.draw.draw_framebuffer = draw_fbo.handle;
state.draw.shader_program = program.handle; state.draw.shader_program = program.handle;
state.draw.vertex_array = vao.handle; state.draw.vertex_array = vao.handle;
@ -152,8 +152,8 @@ void RGBA4toRGB5A1::Reinterpret(const Surface& source, VideoCore::Rect2D src_rec
static_cast<GLsizei>(dst_rect.GetHeight())}; static_cast<GLsizei>(dst_rect.GetHeight())};
state.Apply(); state.Apply();
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dest.Handle(),
dest.texture.handle, 0); 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
glUniform2i(dst_size_loc, dst_rect.GetWidth(), dst_rect.GetHeight()); glUniform2i(dst_size_loc, dst_rect.GetWidth(), dst_rect.GetHeight());

View File

@ -412,7 +412,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
auto surface = res_cache.GetTextureSurface(info); auto surface = res_cache.GetTextureSurface(info);
if (surface != nullptr) { if (surface != nullptr) {
target = surface->texture.handle; target = surface->Handle();
} else { } else {
target = 0; target = 0;
} }
@ -431,7 +431,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
case TextureType::Shadow2D: { case TextureType::Shadow2D: {
const auto surface = res_cache.GetTextureSurface(texture); const auto surface = res_cache.GetTextureSurface(texture);
if (surface) { if (surface) {
state.image_shadow_texture_px = surface->texture.handle; state.image_shadow_texture_px = surface->Handle();
} else { } else {
state.image_shadow_texture_px = 0; state.image_shadow_texture_px = 0;
} }
@ -463,7 +463,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
.format = texture.format}; .format = texture.format};
state.texture_cube_unit.texture_cube = state.texture_cube_unit.texture_cube =
res_cache.GetTextureCube(config)->texture.handle; res_cache.GetTextureCube(config)->Handle();
state.texture_cube_unit.sampler = sampler.Handle(); state.texture_cube_unit.sampler = sampler.Handle();
state.texture_units[texture_index].texture_2d = 0; state.texture_units[texture_index].texture_2d = 0;
@ -480,7 +480,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
auto surface = res_cache.GetTextureSurface(texture); auto surface = res_cache.GetTextureSurface(texture);
if (surface != nullptr) { if (surface != nullptr) {
state.texture_units[texture_index].texture_2d = surface->texture.handle; state.texture_units[texture_index].texture_2d = surface->Handle();
} else { } else {
// Can occur when texture addr is null or its memory is unmapped/invalid // Can occur when texture addr is null or its memory is unmapped/invalid
// HACK: In this case, the correct behaviour for the PICA is to use the last // HACK: In this case, the correct behaviour for the PICA is to use the last
@ -688,14 +688,14 @@ bool RasterizerOpenGL::AccelerateDisplay(const GPU::Regs::FramebufferConfig& con
return false; return false;
} }
u32 scaled_width = src_surface->GetScaledWidth(); const u32 scaled_width = src_surface->GetScaledWidth();
u32 scaled_height = src_surface->GetScaledHeight(); const u32 scaled_height = src_surface->GetScaledHeight();
screen_info.display_texcoords = Common::Rectangle<float>( screen_info.display_texcoords = Common::Rectangle<float>(
(float)src_rect.bottom / (float)scaled_height, (float)src_rect.left / (float)scaled_width, (float)src_rect.bottom / (float)scaled_height, (float)src_rect.left / (float)scaled_width,
(float)src_rect.top / (float)scaled_height, (float)src_rect.right / (float)scaled_width); (float)src_rect.top / (float)scaled_height, (float)src_rect.right / (float)scaled_width);
screen_info.display_texture = src_surface->texture.handle; screen_info.display_texture = src_surface->Handle();
return true; return true;
} }

View File

@ -81,6 +81,8 @@ TextureRuntime::TextureRuntime(Driver& driver)
Register(VideoCore::PixelFormat::RGB5A1, std::make_unique<RGBA4toRGB5A1>()); Register(VideoCore::PixelFormat::RGB5A1, std::make_unique<RGBA4toRGB5A1>());
} }
TextureRuntime::~TextureRuntime() = default;
StagingData TextureRuntime::FindStaging(u32 size, bool upload) { StagingData TextureRuntime::FindStaging(u32 size, bool upload) {
if (!upload) { if (!upload) {
if (size > download_buffer.size()) { if (size > download_buffer.size()) {
@ -171,13 +173,12 @@ bool TextureRuntime::ClearTexture(Surface& surface, const VideoCore::TextureClea
state.draw.draw_framebuffer = draw_fbo.handle; state.draw.draw_framebuffer = draw_fbo.handle;
state.Apply(); state.Apply();
GLint handle = surface.texture.handle;
switch (surface.type) { switch (surface.type) {
case VideoCore::SurfaceType::Color: case VideoCore::SurfaceType::Color:
case VideoCore::SurfaceType::Texture: case VideoCore::SurfaceType::Texture:
case VideoCore::SurfaceType::Fill: case VideoCore::SurfaceType::Fill:
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle, glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
clear.texture_level); surface.Handle(), clear.texture_level);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
0); 0);
@ -191,8 +192,8 @@ bool TextureRuntime::ClearTexture(Surface& surface, const VideoCore::TextureClea
break; break;
case VideoCore::SurfaceType::Depth: case VideoCore::SurfaceType::Depth:
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, handle, glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
clear.texture_level); surface.Handle(), clear.texture_level);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
state.depth.write_mask = GL_TRUE; state.depth.write_mask = GL_TRUE;
@ -203,7 +204,7 @@ bool TextureRuntime::ClearTexture(Surface& surface, const VideoCore::TextureClea
case VideoCore::SurfaceType::DepthStencil: case VideoCore::SurfaceType::DepthStencil:
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
handle, clear.texture_level); surface.Handle(), clear.texture_level);
state.depth.write_mask = GL_TRUE; state.depth.write_mask = GL_TRUE;
state.stencil.write_mask = -1; state.stencil.write_mask = -1;
@ -224,8 +225,8 @@ bool TextureRuntime::CopyTextures(Surface& source, Surface& dest,
source.texture_type == TextureType::CubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; source.texture_type == TextureType::CubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
const GLenum dst_textarget = const GLenum dst_textarget =
dest.texture_type == TextureType::CubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; dest.texture_type == TextureType::CubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
glCopyImageSubData(source.texture.handle, src_textarget, copy.src_level, copy.src_offset.x, glCopyImageSubData(source.Handle(), src_textarget, copy.src_level, copy.src_offset.x,
copy.src_offset.y, copy.src_layer, dest.texture.handle, dst_textarget, copy.src_offset.y, copy.src_layer, dest.Handle(), dst_textarget,
copy.dst_level, copy.dst_offset.x, copy.dst_offset.y, copy.dst_layer, copy.dst_level, copy.dst_offset.x, copy.dst_offset.y, copy.dst_layer,
copy.extent.width, copy.extent.height, 1); copy.extent.width, copy.extent.height, 1);
return true; return true;
@ -245,12 +246,12 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
? GL_TEXTURE_CUBE_MAP_POSITIVE_X + blit.src_layer ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + blit.src_layer
: GL_TEXTURE_2D; : GL_TEXTURE_2D;
BindFramebuffer(GL_READ_FRAMEBUFFER, blit.src_level, src_textarget, source.type, BindFramebuffer(GL_READ_FRAMEBUFFER, blit.src_level, src_textarget, source.type,
source.texture); source.Handle());
const GLenum dst_textarget = dest.texture_type == TextureType::CubeMap const GLenum dst_textarget = dest.texture_type == TextureType::CubeMap
? GL_TEXTURE_CUBE_MAP_POSITIVE_X + blit.dst_layer ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + blit.dst_layer
: GL_TEXTURE_2D; : GL_TEXTURE_2D;
BindFramebuffer(GL_DRAW_FRAMEBUFFER, blit.dst_level, dst_textarget, dest.type, dest.texture); BindFramebuffer(GL_DRAW_FRAMEBUFFER, blit.dst_level, dst_textarget, dest.type, dest.Handle());
// TODO (wwylele): use GL_NEAREST for shadow map texture // TODO (wwylele): use GL_NEAREST for shadow map texture
// Note: shadow map is treated as RGBA8 format in PICA, as well as in the rasterizer cache, but // Note: shadow map is treated as RGBA8 format in PICA, as well as in the rasterizer cache, but
@ -271,7 +272,7 @@ void TextureRuntime::GenerateMipmaps(Surface& surface, u32 max_level) {
SCOPE_EXIT({ prev_state.Apply(); }); SCOPE_EXIT({ prev_state.Apply(); });
OpenGLState state{}; OpenGLState state{};
state.texture_units[0].texture_2d = surface.texture.handle; state.texture_units[0].texture_2d = surface.Handle();
state.Apply(); state.Apply();
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
@ -290,25 +291,24 @@ bool TextureRuntime::NeedsConvertion(VideoCore::PixelFormat format) const {
} }
void TextureRuntime::BindFramebuffer(GLenum target, GLint level, GLenum textarget, void TextureRuntime::BindFramebuffer(GLenum target, GLint level, GLenum textarget,
VideoCore::SurfaceType type, OGLTexture& texture) const { VideoCore::SurfaceType type, GLuint handle) const {
const GLint framebuffer = target == GL_DRAW_FRAMEBUFFER ? draw_fbo.handle : read_fbo.handle; const GLint framebuffer = target == GL_DRAW_FRAMEBUFFER ? draw_fbo.handle : read_fbo.handle;
glBindFramebuffer(target, framebuffer); glBindFramebuffer(target, framebuffer);
switch (type) { switch (type) {
case VideoCore::SurfaceType::Color: case VideoCore::SurfaceType::Color:
case VideoCore::SurfaceType::Texture: case VideoCore::SurfaceType::Texture:
glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0, textarget, texture.handle, level); glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0, textarget, handle, level);
glFramebufferTexture2D(target, GL_DEPTH_STENCIL_ATTACHMENT, textarget, 0, 0); glFramebufferTexture2D(target, GL_DEPTH_STENCIL_ATTACHMENT, textarget, 0, 0);
break; break;
case VideoCore::SurfaceType::Depth: case VideoCore::SurfaceType::Depth:
glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0, textarget, 0, 0); glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0, textarget, 0, 0);
glFramebufferTexture2D(target, GL_DEPTH_ATTACHMENT, textarget, texture.handle, level); glFramebufferTexture2D(target, GL_DEPTH_ATTACHMENT, textarget, handle, level);
glFramebufferTexture2D(target, GL_STENCIL_ATTACHMENT, textarget, 0, 0); glFramebufferTexture2D(target, GL_STENCIL_ATTACHMENT, textarget, 0, 0);
break; break;
case VideoCore::SurfaceType::DepthStencil: case VideoCore::SurfaceType::DepthStencil:
glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0, textarget, 0, 0); glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0, textarget, 0, 0);
glFramebufferTexture2D(target, GL_DEPTH_STENCIL_ATTACHMENT, textarget, texture.handle, glFramebufferTexture2D(target, GL_DEPTH_STENCIL_ATTACHMENT, textarget, handle, level);
level);
break; break;
default: default:
UNREACHABLE_MSG("Invalid surface type!"); UNREACHABLE_MSG("Invalid surface type!");
@ -381,7 +381,7 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download, const Stagi
glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(rect.GetWidth())); glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(rect.GetWidth()));
runtime.BindFramebuffer(GL_READ_FRAMEBUFFER, download.texture_level, GL_TEXTURE_2D, type, runtime.BindFramebuffer(GL_READ_FRAMEBUFFER, download.texture_level, GL_TEXTURE_2D, type,
texture); texture.handle);
const auto& tuple = runtime.GetFormatTuple(pixel_format); const auto& tuple = runtime.GetFormatTuple(pixel_format);
glReadPixels(rect.left, rect.bottom, rect.GetWidth(), rect.GetHeight(), tuple.format, glReadPixels(rect.left, rect.bottom, rect.GetWidth(), rect.GetHeight(), tuple.format,
@ -455,7 +455,7 @@ void Surface::ScaledDownload(const VideoCore::BufferTextureCopy& download,
const auto& tuple = runtime.GetFormatTuple(pixel_format); const auto& tuple = runtime.GetFormatTuple(pixel_format);
if (driver.IsOpenGLES()) { if (driver.IsOpenGLES()) {
runtime.BindFramebuffer(GL_READ_FRAMEBUFFER, download.texture_level, GL_TEXTURE_2D, type, runtime.BindFramebuffer(GL_READ_FRAMEBUFFER, download.texture_level, GL_TEXTURE_2D, type,
unscaled_surface.texture); unscaled_surface.Handle());
glReadPixels(0, 0, rect_width, rect_height, tuple.format, tuple.type, glReadPixels(0, 0, rect_width, rect_height, tuple.format, tuple.type,
staging.mapped.data()); staging.mapped.data());
} else { } else {

View File

@ -40,8 +40,8 @@ class TextureRuntime {
friend class Framebuffer; friend class Framebuffer;
public: public:
TextureRuntime(Driver& driver); explicit TextureRuntime(Driver& driver);
~TextureRuntime() = default; ~TextureRuntime();
/// Maps an internal staging buffer of the provided size of pixel uploads/downloads /// Maps an internal staging buffer of the provided size of pixel uploads/downloads
StagingData FindStaging(u32 size, bool upload); StagingData FindStaging(u32 size, bool upload);
@ -78,7 +78,7 @@ public:
private: private:
/// Returns the framebuffer used for texture downloads /// Returns the framebuffer used for texture downloads
void BindFramebuffer(GLenum target, GLint level, GLenum textarget, VideoCore::SurfaceType type, void BindFramebuffer(GLenum target, GLint level, GLenum textarget, VideoCore::SurfaceType type,
OGLTexture& texture) const; GLuint handle) const;
/// Returns the OpenGL driver class /// Returns the OpenGL driver class
const Driver& GetDriver() const { const Driver& GetDriver() const {
@ -103,7 +103,7 @@ private:
class Surface : public VideoCore::SurfaceBase { class Surface : public VideoCore::SurfaceBase {
public: public:
Surface(VideoCore::SurfaceParams& params, TextureRuntime& runtime); explicit Surface(VideoCore::SurfaceParams& params, TextureRuntime& runtime);
~Surface(); ~Surface();
/// Returns the surface image handle /// Returns the surface image handle
@ -132,8 +132,6 @@ private:
private: private:
TextureRuntime& runtime; TextureRuntime& runtime;
const Driver& driver; const Driver& driver;
public:
OGLTexture texture{}; OGLTexture texture{};
}; };

View File

@ -21,6 +21,7 @@ namespace Vulkan {
using VideoCore::GetFormatType; using VideoCore::GetFormatType;
using VideoCore::MipLevels; using VideoCore::MipLevels;
using VideoCore::PixelFormatAsString; using VideoCore::PixelFormatAsString;
using VideoCore::TextureType;
struct RecordParams { struct RecordParams {
vk::ImageAspectFlags aspect; vk::ImageAspectFlags aspect;
@ -130,9 +131,6 @@ TextureRuntime::~TextureRuntime() {
for (const auto& [key, alloc] : texture_recycler) { for (const auto& [key, alloc] : texture_recycler) {
vmaDestroyImage(allocator, alloc.image, alloc.allocation); vmaDestroyImage(allocator, alloc.image, alloc.allocation);
if (alloc.base_view && alloc.base_view != alloc.image_view) {
device.destroyImageView(alloc.base_view);
}
device.destroyImageView(alloc.image_view); device.destroyImageView(alloc.image_view);
if (alloc.depth_view) { if (alloc.depth_view) {
device.destroyImageView(alloc.depth_view); device.destroyImageView(alloc.depth_view);
@ -162,23 +160,19 @@ void TextureRuntime::Finish() {
scheduler.Finish(); scheduler.Finish();
} }
ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, u32 levels, Allocation TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
VideoCore::PixelFormat format, VideoCore::TextureType type) { VideoCore::PixelFormat format, VideoCore::TextureType type) {
const FormatTraits traits = instance.GetTraits(format); const FormatTraits traits = instance.GetTraits(format);
return Allocate(width, height, levels, format, type, traits.native, traits.usage, return Allocate(width, height, levels, format, type, traits.native, traits.usage,
traits.aspect); traits.aspect);
} }
ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, u32 levels, Allocation TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
VideoCore::PixelFormat pixel_format, VideoCore::PixelFormat pixel_format,
VideoCore::TextureType type, vk::Format format, VideoCore::TextureType type, vk::Format format,
vk::ImageUsageFlags usage, vk::ImageAspectFlags aspect) { vk::ImageUsageFlags usage, vk::ImageAspectFlags aspect) {
MICROPROFILE_SCOPE(Vulkan_ImageAlloc); MICROPROFILE_SCOPE(Vulkan_ImageAlloc);
ImageAlloc alloc{};
alloc.format = format;
alloc.aspect = aspect;
// The internal format does not provide enough guarantee of texture uniqueness // The internal format does not provide enough guarantee of texture uniqueness
// especially when many pixel formats fallback to RGBA8 // especially when many pixel formats fallback to RGBA8
ASSERT(pixel_format != VideoCore::PixelFormat::Invalid); ASSERT(pixel_format != VideoCore::PixelFormat::Invalid);
@ -191,9 +185,8 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
.levels = levels, .levels = levels,
}; };
// Attempt to recycle an unused allocation
if (auto it = texture_recycler.find(key); it != texture_recycler.end()) { if (auto it = texture_recycler.find(key); it != texture_recycler.end()) {
ImageAlloc alloc = std::move(it->second); Allocation alloc = std::move(it->second);
texture_recycler.erase(it); texture_recycler.erase(it);
return alloc; return alloc;
} }
@ -242,24 +235,23 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
VkImage unsafe_image{}; VkImage unsafe_image{};
VkImageCreateInfo unsafe_image_info = static_cast<VkImageCreateInfo>(image_info); VkImageCreateInfo unsafe_image_info = static_cast<VkImageCreateInfo>(image_info);
VmaAllocation allocation{};
VkResult result = vmaCreateImage(instance.GetAllocator(), &unsafe_image_info, &alloc_info, VkResult result = vmaCreateImage(instance.GetAllocator(), &unsafe_image_info, &alloc_info,
&unsafe_image, &alloc.allocation, nullptr); &unsafe_image, &allocation, nullptr);
if (result != VK_SUCCESS) [[unlikely]] { if (result != VK_SUCCESS) [[unlikely]] {
LOG_CRITICAL(Render_Vulkan, "Failed allocating texture with error {}", result); LOG_CRITICAL(Render_Vulkan, "Failed allocating texture with error {}", result);
UNREACHABLE(); UNREACHABLE();
} }
const vk::Image image{unsafe_image};
const vk::ImageViewType view_type =
type == VideoCore::TextureType::CubeMap ? vk::ImageViewType::eCube : vk::ImageViewType::e2D;
alloc.image = vk::Image{unsafe_image};
const vk::ImageViewCreateInfo view_info = { const vk::ImageViewCreateInfo view_info = {
.image = alloc.image, .image = image,
.viewType = view_type, .viewType =
type == TextureType::CubeMap ? vk::ImageViewType::eCube : vk::ImageViewType::e2D,
.format = format, .format = format,
.subresourceRange{ .subresourceRange{
.aspectMask = alloc.aspect, .aspectMask = aspect,
.baseMipLevel = 0, .baseMipLevel = 0,
.levelCount = levels, .levelCount = levels,
.baseArrayLayer = 0, .baseArrayLayer = 0,
@ -268,13 +260,10 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
}; };
vk::Device device = instance.GetDevice(); vk::Device device = instance.GetDevice();
alloc.image_view = device.createImageView(view_info); const vk::ImageView image_view = device.createImageView(view_info);
if (levels == 1) {
alloc.base_view = alloc.image_view;
}
renderpass_cache.ExitRenderpass(); renderpass_cache.ExitRenderpass();
scheduler.Record([image = alloc.image, aspect = alloc.aspect](vk::CommandBuffer cmdbuf) { scheduler.Record([image, aspect](vk::CommandBuffer cmdbuf) {
const vk::ImageMemoryBarrier init_barrier = { const vk::ImageMemoryBarrier init_barrier = {
.srcAccessMask = vk::AccessFlagBits::eNone, .srcAccessMask = vk::AccessFlagBits::eNone,
.dstAccessMask = vk::AccessFlagBits::eNone, .dstAccessMask = vk::AccessFlagBits::eNone,
@ -297,10 +286,16 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
vk::DependencyFlagBits::eByRegion, {}, {}, init_barrier); vk::DependencyFlagBits::eByRegion, {}, {}, init_barrier);
}); });
return alloc; return Allocation{
.image = image,
.image_view = image_view,
.allocation = allocation,
.aspect = aspect,
.format = format,
};
} }
void TextureRuntime::Recycle(const HostTextureTag tag, ImageAlloc&& alloc) { void TextureRuntime::Recycle(const HostTextureTag tag, Allocation&& alloc) {
texture_recycler.emplace(tag, std::move(alloc)); texture_recycler.emplace(tag, std::move(alloc));
} }
@ -745,7 +740,7 @@ bool TextureRuntime::NeedsConvertion(VideoCore::PixelFormat format) const {
Surface::Surface(const VideoCore::SurfaceParams& params, TextureRuntime& runtime) Surface::Surface(const VideoCore::SurfaceParams& params, TextureRuntime& runtime)
: VideoCore::SurfaceBase{params}, runtime{runtime}, instance{runtime.GetInstance()}, : VideoCore::SurfaceBase{params}, runtime{runtime}, instance{runtime.GetInstance()},
scheduler{runtime.GetScheduler()}, traits{instance.GetTraits(pixel_format)} { scheduler{runtime.GetScheduler()} {
if (pixel_format != VideoCore::PixelFormat::Invalid) { if (pixel_format != VideoCore::PixelFormat::Invalid) {
alloc = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), levels, params.pixel_format, alloc = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), levels, params.pixel_format,
@ -994,28 +989,6 @@ vk::PipelineStageFlags Surface::PipelineStageFlags() const noexcept {
: vk::PipelineStageFlagBits::eNone); : vk::PipelineStageFlagBits::eNone);
} }
vk::ImageView Surface::FramebufferView() noexcept {
vk::ImageView& base_view = alloc.base_view;
if (base_view) {
return base_view;
}
const vk::ImageViewCreateInfo base_view_info = {
.image = alloc.image,
.viewType = vk::ImageViewType::e2D,
.format = instance.GetTraits(pixel_format).native,
.subresourceRange{
.aspectMask = alloc.aspect,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
base_view = instance.GetDevice().createImageView(base_view_info);
return base_view;
}
vk::ImageView Surface::DepthView() noexcept { vk::ImageView Surface::DepthView() noexcept {
vk::ImageView& depth_view = alloc.depth_view; vk::ImageView& depth_view = alloc.depth_view;
if (depth_view) { if (depth_view) {

View File

@ -26,26 +26,15 @@ struct StagingData {
u64 buffer_offset = 0; u64 buffer_offset = 0;
}; };
struct ImageAlloc { struct Allocation {
ImageAlloc() = default;
ImageAlloc(const ImageAlloc&) = delete;
ImageAlloc& operator=(const ImageAlloc&) = delete;
ImageAlloc(ImageAlloc&&) = default;
ImageAlloc& operator=(ImageAlloc&&) = default;
vk::Image image; vk::Image image;
vk::ImageView image_view; vk::ImageView image_view;
vk::ImageView base_view;
vk::ImageView depth_view; vk::ImageView depth_view;
vk::ImageView stencil_view; vk::ImageView stencil_view;
vk::ImageView storage_view; vk::ImageView storage_view;
VmaAllocation allocation; VmaAllocation allocation;
vk::ImageUsageFlags usage; vk::ImageAspectFlags aspect;
vk::Format format; vk::Format format;
vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor;
vk::ImageLayout layout;
}; };
struct HostTextureTag { struct HostTextureTag {
@ -98,17 +87,17 @@ public:
void Finish(); void Finish();
/// Takes back ownership of the allocation for recycling /// Takes back ownership of the allocation for recycling
void Recycle(const HostTextureTag tag, ImageAlloc&& alloc); void Recycle(const HostTextureTag tag, Allocation&& alloc);
/// Maps an internal staging buffer of the provided size of pixel uploads/downloads /// Maps an internal staging buffer of the provided size of pixel uploads/downloads
[[nodiscard]] StagingData FindStaging(u32 size, bool upload); [[nodiscard]] StagingData FindStaging(u32 size, bool upload);
/// Allocates a vulkan image possibly resusing an existing one /// Allocates a vulkan image possibly resusing an existing one
[[nodiscard]] ImageAlloc Allocate(u32 width, u32 height, u32 levels, [[nodiscard]] Allocation Allocate(u32 width, u32 height, u32 levels,
VideoCore::PixelFormat format, VideoCore::TextureType type); VideoCore::PixelFormat format, VideoCore::TextureType type);
/// Allocates a vulkan image /// Allocates a vulkan image
[[nodiscard]] ImageAlloc Allocate(u32 width, u32 height, u32 levels, [[nodiscard]] Allocation Allocate(u32 width, u32 height, u32 levels,
VideoCore::PixelFormat pixel_format, VideoCore::PixelFormat pixel_format,
VideoCore::TextureType type, vk::Format format, VideoCore::TextureType type, vk::Format format,
vk::ImageUsageFlags usage, vk::ImageAspectFlags aspect); vk::ImageUsageFlags usage, vk::ImageAspectFlags aspect);
@ -159,7 +148,7 @@ private:
StreamBuffer upload_buffer; StreamBuffer upload_buffer;
StreamBuffer download_buffer; StreamBuffer download_buffer;
std::array<ReinterpreterList, VideoCore::PIXEL_FORMAT_COUNT> reinterpreters; std::array<ReinterpreterList, VideoCore::PIXEL_FORMAT_COUNT> reinterpreters;
std::unordered_multimap<HostTextureTag, ImageAlloc> texture_recycler; std::unordered_multimap<HostTextureTag, Allocation> texture_recycler;
}; };
class Surface : public VideoCore::SurfaceBase { class Surface : public VideoCore::SurfaceBase {
@ -201,9 +190,6 @@ public:
/// Returns the pipeline stage flags indicative of the surface /// Returns the pipeline stage flags indicative of the surface
vk::PipelineStageFlags PipelineStageFlags() const noexcept; vk::PipelineStageFlags PipelineStageFlags() const noexcept;
/// Returns an image view used to create a framebuffer
vk::ImageView FramebufferView() noexcept;
/// Returns the depth only image view of the surface /// Returns the depth only image view of the surface
vk::ImageView DepthView() noexcept; vk::ImageView DepthView() noexcept;
@ -228,8 +214,7 @@ private:
TextureRuntime& runtime; TextureRuntime& runtime;
const Instance& instance; const Instance& instance;
Scheduler& scheduler; Scheduler& scheduler;
ImageAlloc alloc; Allocation alloc;
FormatTraits traits;
bool is_framebuffer{}; bool is_framebuffer{};
bool is_storage{}; bool is_storage{};
}; };