@ -14,6 +14,7 @@
# include "video_core/host_shaders/block_linear_unswizzle_2d_comp.h"
# include "video_core/host_shaders/block_linear_unswizzle_3d_comp.h"
# include "video_core/host_shaders/opengl_copy_bc4_comp.h"
# include "video_core/host_shaders/opengl_copy_bgra_comp.h"
# include "video_core/host_shaders/pitch_unswizzle_comp.h"
# include "video_core/renderer_opengl/gl_resource_manager.h"
# include "video_core/renderer_opengl/gl_shader_manager.h"
@ -48,6 +49,11 @@ OGLProgram MakeProgram(std::string_view source) {
return program ;
}
size_t NumPixelsInCopy ( const VideoCommon : : ImageCopy & copy ) {
return static_cast < size_t > ( copy . extent . width * copy . extent . height *
copy . src_subresource . num_layers ) ;
}
} // Anonymous namespace
UtilShaders : : UtilShaders ( ProgramManager & program_manager_ )
@ -55,6 +61,7 @@ UtilShaders::UtilShaders(ProgramManager& program_manager_)
block_linear_unswizzle_2d_program ( MakeProgram ( BLOCK_LINEAR_UNSWIZZLE_2D_COMP ) ) ,
block_linear_unswizzle_3d_program ( MakeProgram ( BLOCK_LINEAR_UNSWIZZLE_3D_COMP ) ) ,
pitch_unswizzle_program ( MakeProgram ( PITCH_UNSWIZZLE_COMP ) ) ,
copy_bgra_program ( MakeProgram ( OPENGL_COPY_BGRA_COMP ) ) ,
copy_bc4_program ( MakeProgram ( OPENGL_COPY_BC4_COMP ) ) {
const auto swizzle_table = Tegra : : Texture : : MakeSwizzleTable ( ) ;
swizzle_table_buffer . Create ( ) ;
@ -205,6 +212,43 @@ void UtilShaders::CopyBC4(Image& dst_image, Image& src_image, std::span<const Im
program_manager . RestoreGuestCompute ( ) ;
}
void UtilShaders : : CopyBGR ( Image & dst_image , Image & src_image ,
std : : span < const VideoCommon : : ImageCopy > copies ) {
static constexpr GLuint BINDING_INPUT_IMAGE = 0 ;
static constexpr GLuint BINDING_OUTPUT_IMAGE = 1 ;
static constexpr VideoCommon : : Offset3D zero_offset { 0 , 0 , 0 } ;
const u32 bytes_per_block = BytesPerBlock ( dst_image . info . format ) ;
switch ( bytes_per_block ) {
case 2 :
// BGR565 copy
for ( const ImageCopy & copy : copies ) {
ASSERT ( copy . src_offset = = zero_offset ) ;
ASSERT ( copy . dst_offset = = zero_offset ) ;
bgr_copy_pass . Execute ( dst_image , src_image , copy ) ;
}
break ;
case 4 : {
// BGRA8 copy
program_manager . BindHostCompute ( copy_bgra_program . handle ) ;
constexpr GLenum FORMAT = GL_RGBA8 ;
for ( const ImageCopy & copy : copies ) {
ASSERT ( copy . src_offset = = zero_offset ) ;
ASSERT ( copy . dst_offset = = zero_offset ) ;
glBindImageTexture ( BINDING_INPUT_IMAGE , src_image . StorageHandle ( ) ,
copy . src_subresource . base_level , GL_FALSE , 0 , GL_READ_ONLY , FORMAT ) ;
glBindImageTexture ( BINDING_OUTPUT_IMAGE , dst_image . StorageHandle ( ) ,
copy . dst_subresource . base_level , GL_FALSE , 0 , GL_WRITE_ONLY , FORMAT ) ;
glDispatchCompute ( copy . extent . width , copy . extent . height , copy . extent . depth ) ;
}
program_manager . RestoreGuestCompute ( ) ;
break ;
}
default :
UNREACHABLE ( ) ;
break ;
}
}
GLenum StoreFormat ( u32 bytes_per_block ) {
switch ( bytes_per_block ) {
case 1 :
@ -222,4 +266,36 @@ GLenum StoreFormat(u32 bytes_per_block) {
return GL_R8UI ;
}
void Bgr565CopyPass : : Execute ( const Image & dst_image , const Image & src_image ,
const ImageCopy & copy ) {
if ( CopyBufferCreationNeeded ( copy ) ) {
CreateNewCopyBuffer ( copy , GL_TEXTURE_2D_ARRAY , GL_RGB565 ) ;
}
// Copy from source to PBO
glPixelStorei ( GL_PACK_ALIGNMENT , 1 ) ;
glPixelStorei ( GL_PACK_ROW_LENGTH , copy . extent . width ) ;
glBindBuffer ( GL_PIXEL_PACK_BUFFER , bgr16_pbo . handle ) ;
glGetTextureSubImage ( src_image . Handle ( ) , 0 , 0 , 0 , 0 , copy . extent . width , copy . extent . height ,
copy . src_subresource . num_layers , GL_RGB , GL_UNSIGNED_SHORT_5_6_5 ,
static_cast < GLsizei > ( bgr16_pbo_size ) , nullptr ) ;
// Copy from PBO to destination in reverse order
glPixelStorei ( GL_UNPACK_ALIGNMENT , 1 ) ;
glPixelStorei ( GL_UNPACK_ROW_LENGTH , copy . extent . width ) ;
glBindBuffer ( GL_PIXEL_UNPACK_BUFFER , bgr16_pbo . handle ) ;
glTextureSubImage3D ( dst_image . Handle ( ) , 0 , 0 , 0 , 0 , copy . extent . width , copy . extent . height ,
copy . dst_subresource . num_layers , GL_RGB , GL_UNSIGNED_SHORT_5_6_5_REV ,
nullptr ) ;
}
bool Bgr565CopyPass : : CopyBufferCreationNeeded ( const ImageCopy & copy ) {
return bgr16_pbo_size < NumPixelsInCopy ( copy ) * sizeof ( u16 ) ;
}
void Bgr565CopyPass : : CreateNewCopyBuffer ( const ImageCopy & copy , GLenum target , GLuint format ) {
bgr16_pbo . Create ( ) ;
bgr16_pbo_size = NumPixelsInCopy ( copy ) * sizeof ( u16 ) ;
glNamedBufferData ( bgr16_pbo . handle , bgr16_pbo_size , nullptr , GL_STREAM_COPY ) ;
}
} // namespace OpenGL