video_core: Cleanup surface interface
* Remove unused FramebufferView and make the opengl handles private
This commit is contained in:
@ -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());
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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{};
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user