// SPDX-License-Identifier: GPL-2.0-or-later /* The abstract GPU objects call into the classes of the backend in use * (g_video_backend_kind): each backend's classes are final, so these are * direct calls. */ #include "VideoCommon/AbstractFramebuffer.h" #include "VideoCommon/AbstractPipeline.h" #include "VideoCommon/AbstractShader.h" #include "VideoCommon/AbstractStagingTexture.h" #include "VideoCommon/AbstractTexture.h" #include "VideoCommon/VideoBackendKind.h" #include "VideoBackends/Null/NullTexture.h" #include "VideoBackends/Software/SWTexture.h" #ifdef HAS_OPENGL #include "VideoBackends/OGL/OGLPipeline.h" #include "VideoBackends/OGL/OGLShader.h" #include "VideoBackends/OGL/OGLTexture.h" #endif #ifdef HAS_VULKAN #include "VideoBackends/Vulkan/VKPipeline.h" #include "VideoBackends/Vulkan/VKShader.h" #include "VideoBackends/Vulkan/VKTexture.h" #endif #ifdef _WIN32 #include "VideoBackends/D3D/DXPipeline.h" #include "VideoBackends/D3D/DXShader.h" #include "VideoBackends/D3D/DXTexture.h" #include "VideoBackends/D3D12/DX12Pipeline.h" #include "VideoBackends/D3D12/DX12Shader.h" #include "VideoBackends/D3D12/DX12Texture.h" #endif VideoBackendKind g_video_backend_kind = VIDEO_BACKEND_NULL; /* shaders */ void AbstractShaderDelete(AbstractShader* object) { if (!object) return; switch (g_video_backend_kind) { #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: delete static_cast(object); return; #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: delete static_cast(object); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: delete static_cast(object); return; case VIDEO_BACKEND_D3D12: delete static_cast(object); return; #endif default: delete object; return; } } const u8* AbstractShader::GetBinary(size_t* size) const { switch (g_video_backend_kind) { #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: return static_cast(this)->GetBinary(size); #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: return static_cast(this)->GetBinary(size); case VIDEO_BACKEND_D3D12: return static_cast(this)->GetBinary(size); #endif default: *size = 0; return nullptr; } } /* pipelines */ void AbstractPipelineDelete(AbstractPipeline* object) { if (!object) return; switch (g_video_backend_kind) { #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: delete static_cast(object); return; #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: delete static_cast(object); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: delete static_cast(object); return; case VIDEO_BACKEND_D3D12: delete static_cast(object); return; #endif default: delete object; return; } } size_t AbstractPipeline::WriteCacheData(CacheDataReserve reserve, void* ctx) const { switch (g_video_backend_kind) { #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: return static_cast(this)->WriteCacheData(reserve, ctx); #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D12: return static_cast(this)->WriteCacheData(reserve, ctx); #endif default: return 0; } } bool AbstractPipeline::IsReady() const { switch (g_video_backend_kind) { #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: return static_cast(this)->IsReady(); #endif default: return true; } } bool AbstractPipeline::IsBuilding() const { switch (g_video_backend_kind) { #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: return static_cast(this)->IsBuilding(); #endif default: return false; } } /* framebuffers */ void AbstractFramebufferDelete(AbstractFramebuffer* object) { if (!object) return; switch (g_video_backend_kind) { case VIDEO_BACKEND_NULL: delete static_cast(object); return; case VIDEO_BACKEND_SOFTWARE: delete static_cast(object); return; #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: delete static_cast(object); return; #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: delete static_cast(object); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: delete static_cast(object); return; case VIDEO_BACKEND_D3D12: delete static_cast(object); return; #endif default: delete object; return; } } /* textures */ void AbstractTextureDelete(AbstractTexture* object) { if (!object) return; switch (g_video_backend_kind) { case VIDEO_BACKEND_NULL: delete static_cast(object); return; case VIDEO_BACKEND_SOFTWARE: delete static_cast(object); return; #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: delete static_cast(object); return; #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: delete static_cast(object); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: delete static_cast(object); return; case VIDEO_BACKEND_D3D12: delete static_cast(object); return; #endif default: delete object; return; } } void AbstractTexture::CopyRectangleFromTexture(const AbstractTexture* src, const MathUtil::Rectangle& src_rect, u32 src_layer, u32 src_level, const MathUtil::Rectangle& dst_rect, u32 dst_layer, u32 dst_level) { switch (g_video_backend_kind) { case VIDEO_BACKEND_NULL: static_cast(this)->CopyRectangleFromTexture( src, src_rect, src_layer, src_level, dst_rect, dst_layer, dst_level); return; case VIDEO_BACKEND_SOFTWARE: static_cast(this)->CopyRectangleFromTexture(src, src_rect, src_layer, src_level, dst_rect, dst_layer, dst_level); return; #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: static_cast(this)->CopyRectangleFromTexture( src, src_rect, src_layer, src_level, dst_rect, dst_layer, dst_level); return; #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: static_cast(this)->CopyRectangleFromTexture( src, src_rect, src_layer, src_level, dst_rect, dst_layer, dst_level); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: static_cast(this)->CopyRectangleFromTexture( src, src_rect, src_layer, src_level, dst_rect, dst_layer, dst_level); return; case VIDEO_BACKEND_D3D12: static_cast(this)->CopyRectangleFromTexture( src, src_rect, src_layer, src_level, dst_rect, dst_layer, dst_level); return; #endif default: return; } } void AbstractTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle& rect, u32 layer, u32 level) { switch (g_video_backend_kind) { case VIDEO_BACKEND_NULL: static_cast(this)->ResolveFromTexture(src, rect, layer, level); return; case VIDEO_BACKEND_SOFTWARE: static_cast(this)->ResolveFromTexture(src, rect, layer, level); return; #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: static_cast(this)->ResolveFromTexture(src, rect, layer, level); return; #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: static_cast(this)->ResolveFromTexture(src, rect, layer, level); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: static_cast(this)->ResolveFromTexture(src, rect, layer, level); return; case VIDEO_BACKEND_D3D12: static_cast(this)->ResolveFromTexture(src, rect, layer, level); return; #endif default: return; } } void AbstractTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, size_t buffer_size, u32 layer) { switch (g_video_backend_kind) { case VIDEO_BACKEND_NULL: static_cast(this)->Load(level, width, height, row_length, buffer, buffer_size, layer); return; case VIDEO_BACKEND_SOFTWARE: static_cast(this)->Load(level, width, height, row_length, buffer, buffer_size, layer); return; #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: static_cast(this)->Load(level, width, height, row_length, buffer, buffer_size, layer); return; #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: static_cast(this)->Load(level, width, height, row_length, buffer, buffer_size, layer); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: static_cast(this)->Load(level, width, height, row_length, buffer, buffer_size, layer); return; case VIDEO_BACKEND_D3D12: static_cast(this)->Load(level, width, height, row_length, buffer, buffer_size, layer); return; #endif default: return; } } u8* AbstractTexture::LendLoad(u32 level, u32 width, u32 height, u32 row_length, size_t size, u32 layer) { switch (g_video_backend_kind) { #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: return static_cast(this)->LendLoad(level, width, height, row_length, size, layer); #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: return static_cast(this)->LendLoad(level, width, height, row_length, size, layer); #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D12: return static_cast(this)->LendLoad(level, width, height, row_length, size, layer); #endif default: return nullptr; } } void AbstractTexture::CommitLoad() { switch (g_video_backend_kind) { #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: static_cast(this)->CommitLoad(); return; #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: static_cast(this)->CommitLoad(); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D12: static_cast(this)->CommitLoad(); return; #endif default: return; } } void AbstractTexture::FinishedRendering() { switch (g_video_backend_kind) { #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: static_cast(this)->FinishedRendering(); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D12: static_cast(this)->FinishedRendering(); return; #endif default: return; } } /* staging textures */ void AbstractStagingTextureDelete(AbstractStagingTexture* object) { if (!object) return; switch (g_video_backend_kind) { case VIDEO_BACKEND_NULL: delete static_cast(object); return; case VIDEO_BACKEND_SOFTWARE: delete static_cast(object); return; #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: delete static_cast(object); return; #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: delete static_cast(object); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: delete static_cast(object); return; case VIDEO_BACKEND_D3D12: delete static_cast(object); return; #endif default: delete object; return; } } void AbstractStagingTexture::CopyFromTexture(const AbstractTexture* src, const MathUtil::Rectangle& src_rect, u32 src_layer, u32 src_level, const MathUtil::Rectangle& dst_rect) { switch (g_video_backend_kind) { case VIDEO_BACKEND_NULL: static_cast(this)->CopyFromTexture(src, src_rect, src_layer, src_level, dst_rect); return; case VIDEO_BACKEND_SOFTWARE: static_cast(this)->CopyFromTexture(src, src_rect, src_layer, src_level, dst_rect); return; #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: static_cast(this)->CopyFromTexture(src, src_rect, src_layer, src_level, dst_rect); return; #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: static_cast(this)->CopyFromTexture(src, src_rect, src_layer, src_level, dst_rect); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: static_cast(this)->CopyFromTexture(src, src_rect, src_layer, src_level, dst_rect); return; case VIDEO_BACKEND_D3D12: static_cast(this)->CopyFromTexture(src, src_rect, src_layer, src_level, dst_rect); return; #endif default: return; } } void AbstractStagingTexture::CopyToTexture(const MathUtil::Rectangle& src_rect, AbstractTexture* dst, const MathUtil::Rectangle& dst_rect, u32 dst_layer, u32 dst_level) { switch (g_video_backend_kind) { case VIDEO_BACKEND_NULL: static_cast(this)->CopyToTexture(src_rect, dst, dst_rect, dst_layer, dst_level); return; case VIDEO_BACKEND_SOFTWARE: static_cast(this)->CopyToTexture(src_rect, dst, dst_rect, dst_layer, dst_level); return; #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: static_cast(this)->CopyToTexture(src_rect, dst, dst_rect, dst_layer, dst_level); return; #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: static_cast(this)->CopyToTexture(src_rect, dst, dst_rect, dst_layer, dst_level); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: static_cast(this)->CopyToTexture(src_rect, dst, dst_rect, dst_layer, dst_level); return; case VIDEO_BACKEND_D3D12: static_cast(this)->CopyToTexture(src_rect, dst, dst_rect, dst_layer, dst_level); return; #endif default: return; } } bool AbstractStagingTexture::Map() { switch (g_video_backend_kind) { case VIDEO_BACKEND_NULL: return static_cast(this)->Map(); case VIDEO_BACKEND_SOFTWARE: return static_cast(this)->Map(); #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: return static_cast(this)->Map(); #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: return static_cast(this)->Map(); #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: return static_cast(this)->Map(); case VIDEO_BACKEND_D3D12: return static_cast(this)->Map(); #endif default: return false; } } void AbstractStagingTexture::Unmap() { switch (g_video_backend_kind) { case VIDEO_BACKEND_NULL: static_cast(this)->Unmap(); return; case VIDEO_BACKEND_SOFTWARE: static_cast(this)->Unmap(); return; #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: static_cast(this)->Unmap(); return; #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: static_cast(this)->Unmap(); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: static_cast(this)->Unmap(); return; case VIDEO_BACKEND_D3D12: static_cast(this)->Unmap(); return; #endif default: return; } } void AbstractStagingTexture::Flush() { switch (g_video_backend_kind) { case VIDEO_BACKEND_NULL: static_cast(this)->Flush(); return; case VIDEO_BACKEND_SOFTWARE: static_cast(this)->Flush(); return; #ifdef HAS_OPENGL case VIDEO_BACKEND_OGL: static_cast(this)->Flush(); return; #endif #ifdef HAS_VULKAN case VIDEO_BACKEND_VULKAN: static_cast(this)->Flush(); return; #endif #ifdef _WIN32 case VIDEO_BACKEND_D3D11: static_cast(this)->Flush(); return; case VIDEO_BACKEND_D3D12: static_cast(this)->Flush(); return; #endif default: return; } }