diff --git a/src/core/gpu/d3d11_device.cpp b/src/core/gpu/d3d11_device.cpp index b93dd0e6a..1ef0976e2 100644 --- a/src/core/gpu/d3d11_device.cpp +++ b/src/core/gpu/d3d11_device.cpp @@ -510,7 +510,6 @@ void D3D11Device::SetFeatures() m_features.dual_source_blend = true; m_features.per_sample_shading = (feature_level >= D3D_FEATURE_LEVEL_10_1); - m_features.mipmapped_render_targets = true; m_features.noperspective_interpolation = true; m_features.supports_texture_buffers = true; m_features.texture_buffers_emulated_with_ssbo = false; @@ -1153,121 +1152,29 @@ void D3D11Framebuffer::CommitClear(ID3D11DeviceContext1* context) } } -std::unique_ptr D3D11Device::CreateFramebuffer(GPUTexture* rt, u32 rt_layer, u32 rt_level, - GPUTexture* ds, u32 ds_layer, u32 ds_level) +std::unique_ptr D3D11Device::CreateFramebuffer(GPUTexture* rt_or_ds, GPUTexture* ds) { + DebugAssert((rt_or_ds || ds) && (!rt_or_ds || rt_or_ds->IsRenderTarget() || (rt_or_ds->IsDepthStencil() && !ds))); + D3D11Texture* RT = static_cast((rt_or_ds && rt_or_ds->IsDepthStencil()) ? nullptr : rt_or_ds); + D3D11Texture* DS = static_cast((rt_or_ds && rt_or_ds->IsDepthStencil()) ? rt_or_ds : ds); + ComPtr rtv; + if (RT) + { + rtv = RT->GetD3DRTV(); + Assert(rtv); + } + ComPtr dsv; - HRESULT hr; - - Assert(rt || ds); - Assert(!rt || (rt_layer < rt->GetLayers() && rt_level < rt->GetLevels())); - Assert(!ds || (ds_layer < ds->GetLevels() && ds_level < ds->GetLevels())); - Assert(!rt || !ds || - (rt->GetMipWidth(rt_level) == ds->GetMipWidth(ds_level) && - rt->GetMipHeight(rt_level) == ds->GetMipHeight(ds_level))); - - if (rt) + if (DS) { - if (rt_layer == 0 && rt_level == 0) - { - rtv = static_cast(rt)->GetD3DRTV(); - } - else - { - D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {}; - rtv_desc.Format = static_cast(rt)->GetDXGIFormat(); - if (rt->IsMultisampled()) - { - Assert(rt_level == 0); - if (rt->GetLayers() > 1) - { - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY; - rtv_desc.Texture2DMSArray.ArraySize = rt->GetLayers(); - rtv_desc.Texture2DMSArray.FirstArraySlice = rt_layer; - } - else - { - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; - } - } - else - { - if (rt->GetLayers() > 1) - { - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtv_desc.Texture2DArray.ArraySize = rt->GetLayers(); - rtv_desc.Texture2DArray.FirstArraySlice = rt_layer; - rtv_desc.Texture2DArray.MipSlice = rt_level; - } - else - { - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtv_desc.Texture2D.MipSlice = rt_level; - } - } - - if (FAILED(hr = m_device->CreateRenderTargetView(static_cast(rt)->GetD3DTexture(), &rtv_desc, - rtv.GetAddressOf()))) - { - Log_ErrorPrintf("CreateRenderTargetView() failed: %08X", hr); - return {}; - } - } + dsv = DS->GetD3DDSV(); + Assert(dsv); } - if (ds) - { - if (ds_layer == 0 && ds_level == 0) - { - dsv = static_cast(ds)->GetD3DDSV(); - } - else - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = {}; - dsv_desc.Format = static_cast(ds)->GetDXGIFormat(); - if (ds->IsMultisampled()) - { - Assert(rt_level == 0); - if (ds->GetLayers() > 1) - { - dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY; - dsv_desc.Texture2DMSArray.ArraySize = ds->GetLayers(); - dsv_desc.Texture2DMSArray.FirstArraySlice = rt_layer; - } - else - { - dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; - } - } - else - { - if (ds->GetLayers() > 1) - { - dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; - dsv_desc.Texture2DArray.ArraySize = ds->GetLayers(); - dsv_desc.Texture2DArray.FirstArraySlice = rt_layer; - dsv_desc.Texture2DArray.MipSlice = rt_level; - } - else - { - dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; - dsv_desc.Texture2D.MipSlice = rt_level; - } - } - - if (FAILED(hr = m_device->CreateDepthStencilView(static_cast(ds)->GetD3DTexture(), &dsv_desc, - dsv.GetAddressOf()))) - { - Log_ErrorPrintf("CreateDepthStencilView() failed: %08X", hr); - return {}; - } - } - } - - return std::unique_ptr( - new D3D11Framebuffer(rt, ds, rt ? rt->GetMipWidth(rt_level) : ds->GetMipWidth(ds_level), - rt ? rt->GetMipHeight(rt_level) : ds->GetMipHeight(ds_level), std::move(rtv), std::move(dsv))); + return std::unique_ptr(new D3D11Framebuffer(RT, DS, RT ? RT->GetWidth() : DS->GetWidth(), + RT ? RT->GetHeight() : DS->GetHeight(), std::move(rtv), + std::move(dsv))); } D3D11Sampler::D3D11Sampler(ComPtr ss) : m_ss(std::move(ss)) @@ -1854,13 +1761,8 @@ bool D3D11Texture::Create(ID3D11Device* device, u32 width, u32 height, u32 layer Format format, const void* initial_data /* = nullptr */, u32 initial_data_stride /* = 0 */, bool dynamic /* = false */) { - if (width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION || height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION || - layers > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION || (layers > 1 && samples > 1)) - { - Log_ErrorPrintf("Texture bounds (%ux%ux%u, %u mips, %u samples) are too large", width, height, layers, levels, - samples); + if (!ValidateConfig(width, height, layers, layers, samples, type, format)) return false; - } u32 bind_flags = 0; switch (type) diff --git a/src/core/gpu/d3d11_device.h b/src/core/gpu/d3d11_device.h index 727f3a2d6..a0c5cc506 100644 --- a/src/core/gpu/d3d11_device.h +++ b/src/core/gpu/d3d11_device.h @@ -306,9 +306,7 @@ public: void ClearDepth(GPUTexture* t, float d) override; void InvalidateRenderTarget(GPUTexture* t) override; - std::unique_ptr CreateFramebuffer(GPUTexture* rt = nullptr, u32 rt_layer = 0, u32 rt_level = 0, - GPUTexture* ds = nullptr, u32 ds_layer = 0, - u32 ds_level = 0) override; + std::unique_ptr CreateFramebuffer(GPUTexture* rt_or_ds, GPUTexture* ds = nullptr) override; std::unique_ptr CreateShaderFromBinary(GPUShaderStage stage, gsl::span data) override; std::unique_ptr CreateShaderFromSource(GPUShaderStage stage, const std::string_view& source, diff --git a/src/core/gpu/gpu_device.cpp b/src/core/gpu/gpu_device.cpp index a4ed54942..250d2fb65 100644 --- a/src/core/gpu/gpu_device.cpp +++ b/src/core/gpu/gpu_device.cpp @@ -273,13 +273,6 @@ void GPUDevice::Destroy() DestroyDevice(); } -bool GPUDevice::UpdateWindow() -{ - // TODO: REMOVE ME - UnreachableCode(); - return false; -} - bool GPUDevice::SupportsExclusiveFullscreen() const { return false; @@ -419,18 +412,6 @@ bool GPUDevice::SetPostProcessingChain(const std::string_view& config) return true; } -std::string GPUDevice::GetShaderCacheBaseName(const std::string_view& type) const -{ - Panic("Not implemented"); - return {}; -} - -void GPUDevice::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - void GPUDevice::RenderImGui() { GL_SCOPE("RenderImGui"); @@ -483,30 +464,6 @@ void GPUDevice::RenderImGui() } } -void GPUDevice::MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map_ptr, u32* map_space, u32* map_base_vertex) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - -void GPUDevice::UnmapVertexBuffer(u32 vertex_size, u32 vertex_count) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - -void GPUDevice::MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - -void GPUDevice::UnmapIndexBuffer(u32 used_index_count) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - void GPUDevice::UploadVertexBuffer(const void* vertices, u32 vertex_size, u32 vertex_count, u32* base_vertex) { void* map; @@ -525,25 +482,6 @@ void GPUDevice::UploadIndexBuffer(const u16* indices, u32 index_count, u32* base UnmapIndexBuffer(index_count); } -void GPUDevice::PushUniformBuffer(const void* data, u32 data_size) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - -void* GPUDevice::MapUniformBuffer(u32 size) -{ - // TODO: REMOVE ME - UnreachableCode(); - return nullptr; -} - -void GPUDevice::UnmapUniformBuffer(u32 size) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - void GPUDevice::UploadUniformBuffer(const void* data, u32 data_size) { void* map = MapUniformBuffer(data_size); @@ -551,89 +489,12 @@ void GPUDevice::UploadUniformBuffer(const void* data, u32 data_size) UnmapUniformBuffer(data_size); } -void GPUDevice::SetFramebuffer(GPUFramebuffer* fb) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - -void GPUDevice::SetPipeline(GPUPipeline* pipeline) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - -void GPUDevice::SetTextureSampler(u32 slot, GPUTexture* texture, GPUSampler* sampler) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - -void GPUDevice::SetTextureBuffer(u32 slot, GPUTextureBuffer* buffer) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - -void GPUDevice::SetViewport(s32 x, s32 y, s32 width, s32 height) -{ - // TODO: REMOVE ME - // GL needs to invert if writing to the window framebuffer - UnreachableCode(); -} - -void GPUDevice::SetScissor(s32 x, s32 y, s32 width, s32 height) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - void GPUDevice::SetViewportAndScissor(s32 x, s32 y, s32 width, s32 height) { SetViewport(x, y, width, height); SetScissor(x, y, width, height); } -void GPUDevice::Draw(u32 base_vertex, u32 vertex_count) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - -void GPUDevice::DrawIndexed(u32 base_index, u32 index_count, u32 base_vertex) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - -bool GPUDevice::BeginPresent(bool skip_present) -{ - // TODO: REMOVE ME - UnreachableCode(); - return false; -} - -void GPUDevice::EndPresent() -{ - // TODO: REMOVE ME - UnreachableCode(); -} - -void GPUDevice::CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src, - u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - -void GPUDevice::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, - GPUTexture* src, u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, - u32 height) -{ - // TODO: REMOVE ME - UnreachableCode(); -} - void GPUDevice::ClearRenderTarget(GPUTexture* t, u32 c) { t->SetClearColor(c); @@ -649,75 +510,6 @@ void GPUDevice::InvalidateRenderTarget(GPUTexture* t) t->SetState(GPUTexture::State::Invalidated); } -bool GPUDevice::CreateDevice(const std::string_view& adapter) -{ - // TODO: REMOVE ME - UnreachableCode(); - return false; -} - -void GPUDevice::DestroyDevice() -{ - // TODO: REMOVE ME - UnreachableCode(); -} - -std::unique_ptr GPUDevice::CreateShaderFromBinary(GPUShaderStage stage, gsl::span data) -{ - // TODO: REMOVE ME - UnreachableCode(); - return {}; -} - -std::unique_ptr GPUDevice::CreateShaderFromSource(GPUShaderStage stage, const std::string_view& source, - std::vector* out_binary /* = nullptr */) -{ - // TODO: REMOVE ME - UnreachableCode(); - return {}; -} - -std::unique_ptr GPUDevice::CreatePipeline(const GPUPipeline::GraphicsConfig& config) -{ - // TODO: REMOVE ME - UnreachableCode(); - return {}; -} - -void GPUDevice::PushDebugGroup(const char* fmt, ...) -{ -} - -void GPUDevice::PopDebugGroup() -{ -} - -void GPUDevice::InsertDebugMessage(const char* fmt, ...) -{ -} - -std::unique_ptr GPUDevice::CreateSampler(const GPUSampler::Config& config) -{ - // TODO: REMOVE ME - UnreachableCode(); - return {}; -} - -std::unique_ptr GPUDevice::CreateTextureBuffer(GPUTextureBuffer::Format format, u32 size_in_elements) -{ - // TODO: REMOVE ME - UnreachableCode(); - return {}; -} - -std::unique_ptr GPUDevice::CreateFramebuffer(GPUTexture* rt, u32 rt_layer, u32 rt_level, GPUTexture* ds, - u32 ds_layer, u32 ds_level) -{ - // TODO: REMOVE ME - UnreachableCode(); - return {}; -} - std::unique_ptr GPUDevice::CreateShader(GPUShaderStage stage, const std::string_view& source) { std::unique_ptr shader; @@ -1646,7 +1438,8 @@ std::unique_ptr GPUDevice::CreateDeviceForAPI(RenderAPI api) { #ifdef WITH_VULKAN case RenderAPI::Vulkan: - return std::make_unique(); + // return std::make_unique(); + return {}; #endif #ifdef WITH_OPENGL @@ -1657,7 +1450,8 @@ std::unique_ptr GPUDevice::CreateDeviceForAPI(RenderAPI api) #ifdef _WIN32 case RenderAPI::D3D12: - return std::make_unique(); + // return std::make_unique(); + return {}; case RenderAPI::D3D11: return std::make_unique(); diff --git a/src/core/gpu/gpu_device.h b/src/core/gpu/gpu_device.h index ff9357e7d..e58e9bc44 100644 --- a/src/core/gpu/gpu_device.h +++ b/src/core/gpu/gpu_device.h @@ -416,7 +416,6 @@ public: { bool dual_source_blend : 1; bool per_sample_shading : 1; - bool mipmapped_render_targets : 1; bool noperspective_interpolation : 1; bool supports_texture_buffers : 1; bool texture_buffers_emulated_with_ssbo : 1; @@ -488,83 +487,81 @@ public: virtual bool HasSurface() const = 0; virtual void DestroySurface() = 0; - virtual bool UpdateWindow(); + virtual bool UpdateWindow() = 0; virtual bool SupportsExclusiveFullscreen() const; virtual AdapterAndModeList GetAdapterAndModeList() = 0; virtual bool SetPostProcessingChain(const std::string_view& config); - virtual std::string GetShaderCacheBaseName(const std::string_view& type) const; + virtual std::string GetShaderCacheBaseName(const std::string_view& type) const = 0; /// Call when the window size changes externally to recreate any resources. - virtual void ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale); + virtual void ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale) = 0; /// Creates an abstracted RGBA8 texture. If dynamic, the texture can be updated with UpdateTexture() below. virtual std::unique_ptr CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples, GPUTexture::Type type, GPUTexture::Format format, const void* data = nullptr, u32 data_stride = 0, bool dynamic = false) = 0; - virtual std::unique_ptr CreateSampler(const GPUSampler::Config& config); - virtual std::unique_ptr CreateTextureBuffer(GPUTextureBuffer::Format format, u32 size_in_elements); + virtual std::unique_ptr CreateSampler(const GPUSampler::Config& config) = 0; + virtual std::unique_ptr CreateTextureBuffer(GPUTextureBuffer::Format format, u32 size_in_elements) = 0; virtual bool DownloadTexture(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height, void* out_data, u32 out_data_stride) = 0; virtual void CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src, - u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height); + u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height) = 0; virtual void ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src, u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, - u32 height); + u32 height) = 0; virtual void ClearRenderTarget(GPUTexture* t, u32 c); virtual void ClearDepth(GPUTexture* t, float d); virtual void InvalidateRenderTarget(GPUTexture* t); /// Framebuffer abstraction. - virtual std::unique_ptr CreateFramebuffer(GPUTexture* rt = nullptr, u32 rt_layer = 0, - u32 rt_level = 0, GPUTexture* ds = nullptr, - u32 ds_layer = 0, u32 ds_level = 0); + virtual std::unique_ptr CreateFramebuffer(GPUTexture* rt_or_ds, GPUTexture* ds = nullptr) = 0; /// Shader abstraction. // TODO: entry point? source format? std::unique_ptr CreateShader(GPUShaderStage stage, const std::string_view& source); - virtual std::unique_ptr CreatePipeline(const GPUPipeline::GraphicsConfig& config); + virtual std::unique_ptr CreatePipeline(const GPUPipeline::GraphicsConfig& config) = 0; /// Debug messaging. - virtual void PushDebugGroup(const char* fmt, ...); - virtual void PopDebugGroup(); - virtual void InsertDebugMessage(const char* fmt, ...); + virtual void PushDebugGroup(const char* fmt, ...) = 0; + virtual void PopDebugGroup() = 0; + virtual void InsertDebugMessage(const char* fmt, ...) = 0; /// Vertex/index buffer abstraction. - virtual void MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map_ptr, u32* map_space, u32* map_base_vertex); - virtual void UnmapVertexBuffer(u32 vertex_size, u32 vertex_count); - virtual void MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index); - virtual void UnmapIndexBuffer(u32 used_size); + virtual void MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map_ptr, u32* map_space, u32* map_base_vertex) = 0; + virtual void UnmapVertexBuffer(u32 vertex_size, u32 vertex_count) = 0; + virtual void MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index) = 0; + virtual void UnmapIndexBuffer(u32 used_size) = 0; void UploadVertexBuffer(const void* vertices, u32 vertex_size, u32 vertex_count, u32* base_vertex); void UploadIndexBuffer(const DrawIndex* indices, u32 index_count, u32* base_index); /// Uniform buffer abstraction. - virtual void PushUniformBuffer(const void* data, u32 data_size); - virtual void* MapUniformBuffer(u32 size); - virtual void UnmapUniformBuffer(u32 size); + virtual void PushUniformBuffer(const void* data, u32 data_size) = 0; + virtual void* MapUniformBuffer(u32 size) = 0; + virtual void UnmapUniformBuffer(u32 size) = 0; void UploadUniformBuffer(const void* data, u32 data_size); /// Drawing setup abstraction. - virtual void SetFramebuffer(GPUFramebuffer* fb); - virtual void SetPipeline(GPUPipeline* pipeline); - virtual void SetTextureSampler(u32 slot, GPUTexture* texture, GPUSampler* sampler); - virtual void SetTextureBuffer(u32 slot, GPUTextureBuffer* buffer); - virtual void SetViewport(s32 x, s32 y, s32 width, s32 height); - virtual void SetScissor(s32 x, s32 y, s32 width, s32 height); + virtual void SetFramebuffer(GPUFramebuffer* fb) = 0; + virtual void SetPipeline(GPUPipeline* pipeline) = 0; + virtual void SetTextureSampler(u32 slot, GPUTexture* texture, GPUSampler* sampler) = 0; + virtual void SetTextureBuffer(u32 slot, GPUTextureBuffer* buffer) = 0; + virtual void SetViewport(s32 x, s32 y, s32 width, s32 height) = 0; + virtual void SetScissor(s32 x, s32 y, s32 width, s32 height) = 0; void SetViewportAndScissor(s32 x, s32 y, s32 width, s32 height); // Drawing abstraction. - virtual void Draw(u32 vertex_count, u32 base_vertex); - virtual void DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex); + virtual void Draw(u32 vertex_count, u32 base_vertex) = 0; + virtual void DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex) = 0; /// Returns false if the window was completely occluded. - virtual bool BeginPresent(bool skip_present); - virtual void EndPresent(); + virtual bool BeginPresent(bool skip_present) = 0; + virtual void EndPresent() = 0; bool Render(bool skip_present); /// Renders the display with postprocessing to the specified image. @@ -633,12 +630,12 @@ public: bool WriteScreenshotToFile(std::string filename, bool internal_resolution = false, bool compress_on_thread = false); protected: - virtual bool CreateDevice(const std::string_view& adapter); - virtual void DestroyDevice(); + virtual bool CreateDevice(const std::string_view& adapter) = 0; + virtual void DestroyDevice() = 0; - virtual std::unique_ptr CreateShaderFromBinary(GPUShaderStage stage, gsl::span data); + virtual std::unique_ptr CreateShaderFromBinary(GPUShaderStage stage, gsl::span data) = 0; virtual std::unique_ptr CreateShaderFromSource(GPUShaderStage stage, const std::string_view& source, - std::vector* out_binary = nullptr); + std::vector* out_binary = nullptr) = 0; bool AcquireWindow(bool recreate_window); diff --git a/src/core/gpu/gpu_texture.cpp b/src/core/gpu/gpu_texture.cpp index fd4bb2207..51f0bf7f5 100644 --- a/src/core/gpu/gpu_texture.cpp +++ b/src/core/gpu/gpu_texture.cpp @@ -2,8 +2,11 @@ // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "gpu_texture.h" +#include "gpu_device.h" + #include "common/log.h" #include "common/string_util.h" + Log_SetChannel(GPUTexture); GPUTexture::GPUTexture() = default; @@ -54,6 +57,49 @@ bool GPUTexture::IsDepthFormat(Format format) return (format == Format::D16); } +bool GPUTexture::ValidateConfig(u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type, Format format) +{ + if (width > MAX_WIDTH || height > MAX_HEIGHT || layers > MAX_LAYERS || levels > MAX_LEVELS || samples > MAX_SAMPLES) + { + Log_ErrorPrintf("Invalid dimensions: %ux%ux%u %u %u.", width, height, layers, levels, samples); + return false; + } + + const u32 max_texture_size = g_gpu_device->GetMaxTextureSize(); + if (width > max_texture_size || height > max_texture_size) + { + Log_ErrorPrintf("Texture width (%u) or height (%u) exceeds max texture size (%u).", width, height, max_texture_size); + return false; + } + + const u32 max_samples = g_gpu_device->GetMaxMultisamples(); + if (samples > max_samples) + { + Log_ErrorPrintf("Texture samples (%u) exceeds max samples (%u).", samples, max_samples); + return false; + } + + if (samples > 1 && levels > 1) + { + Log_ErrorPrintf("Multisampled textures can't have mip levels."); + return false; + } + + if (layers > 1 && type != Type::Texture) + { + Log_ErrorPrintf("Texture arrays are not supported on targets."); + return false; + } + + if (levels > 1 && type != Type::Texture) + { + Log_ErrorPrintf("Mipmaps are not supported on targets."); + return false; + } + + return true; +} + bool GPUTexture::ConvertTextureDataToRGBA8(u32 width, u32 height, std::vector& texture_data, u32& texture_data_stride, GPUTexture::Format format) { diff --git a/src/core/gpu/gpu_texture.h b/src/core/gpu/gpu_texture.h index 9ef003bf8..66729d39f 100644 --- a/src/core/gpu/gpu_texture.h +++ b/src/core/gpu/gpu_texture.h @@ -109,6 +109,7 @@ public: static u32 GetPixelSize(GPUTexture::Format format); static bool IsDepthFormat(GPUTexture::Format format); + static bool ValidateConfig(u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type, Format format); static bool ConvertTextureDataToRGBA8(u32 width, u32 height, std::vector& texture_data, u32& texture_data_stride, GPUTexture::Format format); diff --git a/src/core/gpu/metal_device.h b/src/core/gpu/metal_device.h index e668dee44..5d4d5ad71 100644 --- a/src/core/gpu/metal_device.h +++ b/src/core/gpu/metal_device.h @@ -212,9 +212,7 @@ public: void ClearDepth(GPUTexture* t, float d) override; void InvalidateRenderTarget(GPUTexture* t) override; - std::unique_ptr CreateFramebuffer(GPUTexture* rt = nullptr, u32 rt_layer = 0, u32 rt_level = 0, - GPUTexture* ds = nullptr, u32 ds_layer = 0, - u32 ds_level = 0) override; + std::unique_ptr CreateFramebuffer(GPUTexture* rt_or_ds, GPUTexture* ds = nullptr) override; std::unique_ptr CreateShaderFromBinary(GPUShaderStage stage, gsl::span data) override; std::unique_ptr CreateShaderFromSource(GPUShaderStage stage, const std::string_view& source, diff --git a/src/core/gpu/metal_device.mm b/src/core/gpu/metal_device.mm index 8e402efe3..196e23242 100644 --- a/src/core/gpu/metal_device.mm +++ b/src/core/gpu/metal_device.mm @@ -970,15 +970,15 @@ std::unique_ptr MetalDevice::CreateTexture(u32 width, u32 height, u3 GPUTexture::Type type, GPUTexture::Format format, const void* data, u32 data_stride, bool dynamic /* = false */) { + if (!GPUTexture::ValidateConfig(width, height, layers, layers, samples, type, format)) + return {}; + + const MTLPixelFormat pixel_format = s_pixel_format_mapping[static_cast(format)]; + if (pixel_format == MTLPixelFormatInvalid) + return {}; + @autoreleasepool { - if (width > m_max_texture_size || height > m_max_texture_size || samples > m_max_multisamples) - return {}; - - const MTLPixelFormat pixel_format = s_pixel_format_mapping[static_cast(format)]; - if (pixel_format == MTLPixelFormatInvalid) - return {}; - MTLTextureDescriptor* desc = [[[MTLTextureDescriptor alloc] init] autorelease]; desc.width = width; desc.height = height; @@ -1115,16 +1115,19 @@ MTLRenderPassDescriptor* MetalFramebuffer::GetDescriptor() const return m_descriptor; } -std::unique_ptr MetalDevice::CreateFramebuffer(GPUTexture* rt, u32 rt_layer, u32 rt_level, - GPUTexture* ds, u32 ds_layer, u32 ds_level) +std::unique_ptr MetalDevice::CreateFramebuffer(GPUTexture* rt_or_ds, GPUTexture* ds) { + DebugAssert((rt_or_ds || ds) && (!rt_or_ds || rt_or_ds->IsRenderTarget() || (rt_or_ds->IsDepthStencil() && !ds))); + MetalTexture* RT = static_cast((rt_or_ds && rt_or_ds->IsDepthStencil()) ? nullptr : rt_or_ds); + MetalTexture* DS = static_cast((rt_or_ds && rt_or_ds->IsDepthStencil()) ? rt_or_ds : ds); + @autoreleasepool { MTLRenderPassDescriptor* desc = [[MTLRenderPassDescriptor renderPassDescriptor] retain]; - id rt_tex = rt ? [static_cast(rt)->GetMTLTexture() retain] : nil; - id ds_tex = ds ? [static_cast(ds)->GetMTLTexture() retain] : nil; + id rt_tex = RT ? [RT->GetMTLTexture() retain] : nil; + id ds_tex = DS ? [DS->GetMTLTexture() retain] : nil; - if (rt) + if (RT) { desc.colorAttachments[0].texture = rt_tex; desc.colorAttachments[0].slice = rt_layer; @@ -1133,7 +1136,7 @@ std::unique_ptr MetalDevice::CreateFramebuffer(GPUTexture* rt, u desc.colorAttachments[0].storeAction = MTLStoreActionStore; } - if (rt) + if (DS) { desc.depthAttachment.texture = ds_tex; desc.depthAttachment.slice = ds_layer; @@ -1142,12 +1145,12 @@ std::unique_ptr MetalDevice::CreateFramebuffer(GPUTexture* rt, u desc.depthAttachment.storeAction = MTLStoreActionStore; } - const u32 width = rt ? rt->GetMipWidth(rt_level) : ds->GetMipWidth(ds_level); - const u32 height = rt ? rt->GetMipHeight(rt_level) : ds->GetMipHeight(ds_level); + const u32 width = RT ? RT->GetWidth() : DS->GetWidth(); + const u32 height = RT ? RT->GetHeight() : DS->GetHeight(); desc.renderTargetWidth = width; desc.renderTargetHeight = height; - return std::unique_ptr(new MetalFramebuffer(rt, ds, width, height, rt_tex, ds_tex, desc)); + return std::unique_ptr(new MetalFramebuffer(RT, DS, width, height, rt_tex, ds_tex, desc)); } } diff --git a/src/core/gpu/opengl_device.cpp b/src/core/gpu/opengl_device.cpp index 7bd22225e..35b4fc336 100644 --- a/src/core/gpu/opengl_device.cpp +++ b/src/core/gpu/opengl_device.cpp @@ -47,7 +47,7 @@ std::unique_ptr OpenGLDevice::CreateTexture(u32 width, u32 height, u const void* data, u32 data_stride, bool dynamic /* = false */) { std::unique_ptr tex(std::make_unique()); - if (!tex->Create(width, height, layers, levels, samples, format, data, data_stride)) + if (!tex->Create(width, height, layers, levels, samples, type, format, data, data_stride)) tex.reset(); return tex; @@ -417,9 +417,6 @@ bool OpenGLDevice::CheckFeatures() m_features.per_sample_shading = GLAD_GL_VERSION_4_0 || GLAD_GL_ES_VERSION_3_2 || GLAD_GL_ARB_sample_shading; - // adaptive smoothing would require texture views, which aren't in GLES. - m_features.mipmapped_render_targets = false; - // noperspective is not supported in GLSL ES. m_features.noperspective_interpolation = !is_gles; return true; diff --git a/src/core/gpu/opengl_device.h b/src/core/gpu/opengl_device.h index e7829d3e8..2d4905088 100644 --- a/src/core/gpu/opengl_device.h +++ b/src/core/gpu/opengl_device.h @@ -69,9 +69,7 @@ public: void ClearDepth(GPUTexture* t, float d) override; void InvalidateRenderTarget(GPUTexture* t) override; - std::unique_ptr CreateFramebuffer(GPUTexture* rt = nullptr, u32 rt_layer = 0, u32 rt_level = 0, - GPUTexture* ds = nullptr, u32 ds_layer = 0, - u32 ds_level = 0) override; + std::unique_ptr CreateFramebuffer(GPUTexture* rt_or_ds, GPUTexture* ds = nullptr) override; std::unique_ptr CreateShaderFromBinary(GPUShaderStage stage, gsl::span data) override; std::unique_ptr CreateShaderFromSource(GPUShaderStage stage, const std::string_view& source, diff --git a/src/core/gpu/opengl_texture.cpp b/src/core/gpu/opengl_texture.cpp index cdfae5c01..531bfe4ff 100644 --- a/src/core/gpu/opengl_texture.cpp +++ b/src/core/gpu/opengl_texture.cpp @@ -59,22 +59,11 @@ bool OpenGLTexture::UseTextureStorage() const return UseTextureStorage(IsMultisampled()); } -bool OpenGLTexture::Create(u32 width, u32 height, u32 layers, u32 levels, u32 samples, Format format, const void* data, - u32 data_pitch) +bool OpenGLTexture::Create(u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type, Format format, + const void* data, u32 data_pitch) { - glGetError(); - - if (width > MAX_WIDTH || height > MAX_HEIGHT || layers > MAX_LAYERS || levels > MAX_LEVELS || samples > MAX_SAMPLES) - { - Log_ErrorPrintf("Invalid dimensions: %ux%ux%u %u %u", width, height, layers, levels, samples); + if (!ValidateConfig(width, height, layers, levels, samples, type, format)) return false; - } - - if (samples > 1 && levels > 1) - { - Log_ErrorPrintf("Multisampled textures can't have mip levels"); - return false; - } if (layers > 1 && data) { @@ -88,6 +77,8 @@ bool OpenGLTexture::Create(u32 width, u32 height, u32 layers, u32 levels, u32 sa OpenGLDevice::BindUpdateTextureUnit(); + glGetError(); + GLuint id; glGenTextures(1, &id); glBindTexture(target, id); @@ -164,67 +155,12 @@ bool OpenGLTexture::Create(u32 width, u32 height, u32 layers, u32 levels, u32 sa m_layers = static_cast(layers); m_levels = static_cast(levels); m_samples = static_cast(samples); + m_type = type; m_format = format; m_state = GPUTexture::State::Dirty; return true; } -#if 0 -void OpenGLTexture::Replace(u32 width, u32 height, GLenum internal_format, GLenum format, GLenum type, const void* data) -{ - Assert(IsValid() && width < MAX_WIDTH && height < MAX_HEIGHT && m_layers == 1 && m_samples == 1 && m_levels == 1); - - const bool size_changed = (width != m_width || height != m_height); - - m_width = static_cast(width); - m_height = static_cast(height); - m_levels = 1; - - const GLenum target = GetGLTarget(); - glBindTexture(target, m_id); - - if (UseTextureStorage()) - { - if (size_changed) - { - if (m_layers > 0) - glTexStorage3D(target, m_levels, internal_format, m_width, m_height, m_levels); - else - glTexStorage2D(target, m_levels, internal_format, m_width, m_height); - } - - glTexSubImage2D(target, 0, 0, 0, m_width, m_height, format, type, data); - } - else - { - glTexImage2D(target, 0, internal_format, width, height, 0, format, type, data); - } -} - -void OpenGLTexture::ReplaceImage(u32 layer, u32 level, GLenum format, GLenum type, const void* data) -{ - Assert(IsValid() && !IsMultisampled()); - - const GLenum target = GetGLTarget(); - if (IsTextureArray()) - glTexSubImage3D(target, level, 0, 0, layer, m_width, m_height, 1, format, type, data); - else - glTexSubImage2D(target, level, 0, 0, m_width, m_height, format, type, data); -} - -void OpenGLTexture::ReplaceSubImage(u32 layer, u32 level, u32 x, u32 y, u32 width, u32 height, GLenum format, - GLenum type, const void* data) -{ - Assert(IsValid() && !IsMultisampled()); - - const GLenum target = GetGLTarget(); - if (IsTextureArray()) - glTexSubImage3D(target, level, x, y, layer, width, height, 1, format, type, data); - else - glTexSubImage2D(target, level, x, y, width, height, format, type, data); -} -#endif - void OpenGLTexture::Destroy() { if (m_id != 0) @@ -458,8 +394,7 @@ void OpenGLFramebuffer::Bind(GLenum target) glBindFramebuffer(target, m_id); } -std::unique_ptr OpenGLDevice::CreateFramebuffer(GPUTexture* rt, u32 rt_layer, u32 rt_level, - GPUTexture* ds, u32 ds_layer, u32 ds_level) +std::unique_ptr OpenGLDevice::CreateFramebuffer(GPUTexture* rt_or_ds, GPUTexture* ds /* = nullptr */) { glGetError(); @@ -467,34 +402,25 @@ std::unique_ptr OpenGLDevice::CreateFramebuffer(GPUTexture* rt, glGenFramebuffers(1, &fbo_id); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id); - OpenGLTexture* RT = static_cast(rt); - OpenGLTexture* DS = static_cast(ds); + DebugAssert((rt_or_ds || ds) && (!rt_or_ds || rt_or_ds->IsRenderTarget() || (rt_or_ds->IsDepthStencil() && !ds))); + OpenGLTexture* RT = static_cast((rt_or_ds && rt_or_ds->IsDepthStencil()) ? nullptr : rt_or_ds); + OpenGLTexture* DS = static_cast((rt_or_ds && rt_or_ds->IsDepthStencil()) ? rt_or_ds : ds); if (RT) - { - if (RT->IsTextureArray()) - glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, fbo_id, RT->GetGLId(), rt_level, rt_layer); - else - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, RT->GetGLId(), rt_level); - } + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, RT->GetGLId(), 0); if (DS) - { - if (DS->IsTextureArray()) - glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, fbo_id, DS->GetGLId(), rt_level, rt_layer); - else - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, DS->GetGLId(), rt_level); - } + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, DS->GetGLId(), 0); if (glGetError() != GL_NO_ERROR || glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { Log_ErrorPrintf("Failed to create GL framebuffer: %u", glGetError()); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_current_framebuffer ? m_current_framebuffer->GetGLId() : 0); glDeleteFramebuffers(1, &fbo_id); return {}; } glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_current_framebuffer ? m_current_framebuffer->GetGLId() : 0); - return std::unique_ptr( - new OpenGLFramebuffer(rt, ds, rt ? rt->GetMipWidth(rt_level) : ds->GetMipWidth(ds_level), - rt ? rt->GetMipHeight(rt_level) : ds->GetMipHeight(ds_level), fbo_id)); + return std::unique_ptr(new OpenGLFramebuffer(RT, DS, RT ? RT->GetWidth() : DS->GetWidth(), + RT ? RT->GetHeight() : DS->GetHeight(), fbo_id)); } void OpenGLDevice::CommitClear(OpenGLTexture* tex) diff --git a/src/core/gpu/opengl_texture.h b/src/core/gpu/opengl_texture.h index a348c43d5..89e7f3d2d 100644 --- a/src/core/gpu/opengl_texture.h +++ b/src/core/gpu/opengl_texture.h @@ -30,8 +30,8 @@ public: void SetDebugName(const std::string_view& name) override; - bool Create(u32 width, u32 height, u32 layers, u32 levels, u32 samples, Format format, const void* data = nullptr, - u32 data_pitch = 0); + bool Create(u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type, Format format, + const void* data = nullptr, u32 data_pitch = 0); void Destroy(); bool UseTextureStorage() const; diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index 2f153d484..4b3abbc2a 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -502,13 +502,10 @@ bool GPU_HW::CreateBuffers() } // vram framebuffer has both colour and depth - if (!(m_vram_framebuffer = - g_gpu_device->CreateFramebuffer(m_vram_texture.get(), 0, 0, m_vram_depth_texture.get(), 0, 0)) || - !(m_vram_update_depth_framebuffer = - g_gpu_device->CreateFramebuffer(nullptr, 0, 0, m_vram_depth_texture.get(), 0, 0)) || - !(m_vram_readback_framebuffer = - g_gpu_device->CreateFramebuffer(m_vram_readback_texture.get(), 0, 0, nullptr, 0, 0)) || - !(m_display_framebuffer = g_gpu_device->CreateFramebuffer(m_display_texture.get(), 0, 0, nullptr, 0, 0))) + if (!(m_vram_framebuffer = g_gpu_device->CreateFramebuffer(m_vram_texture.get(), m_vram_depth_texture.get())) || + !(m_vram_update_depth_framebuffer = g_gpu_device->CreateFramebuffer(m_vram_depth_texture.get())) || + !(m_vram_readback_framebuffer = g_gpu_device->CreateFramebuffer(m_vram_readback_texture.get())) || + !(m_display_framebuffer = g_gpu_device->CreateFramebuffer(m_display_texture.get()))) { return false; }