FBs don't need multi-level now

This commit is contained in:
Stenzek 2023-08-07 23:16:24 +10:00
parent df789e8df9
commit febf864220
13 changed files with 146 additions and 489 deletions

View File

@ -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<GPUFramebuffer> D3D11Device::CreateFramebuffer(GPUTexture* rt, u32 rt_layer, u32 rt_level,
GPUTexture* ds, u32 ds_layer, u32 ds_level)
std::unique_ptr<GPUFramebuffer> 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<D3D11Texture*>((rt_or_ds && rt_or_ds->IsDepthStencil()) ? nullptr : rt_or_ds);
D3D11Texture* DS = static_cast<D3D11Texture*>((rt_or_ds && rt_or_ds->IsDepthStencil()) ? rt_or_ds : ds);
ComPtr<ID3D11RenderTargetView> rtv;
if (RT)
{
rtv = RT->GetD3DRTV();
Assert(rtv);
}
ComPtr<ID3D11DepthStencilView> 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<D3D11Texture*>(rt)->GetD3DRTV();
}
else
{
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {};
rtv_desc.Format = static_cast<D3D11Texture*>(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<D3D11Texture*>(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<D3D11Texture*>(ds)->GetD3DDSV();
}
else
{
D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = {};
dsv_desc.Format = static_cast<D3D11Texture*>(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<D3D11Texture*>(ds)->GetD3DTexture(), &dsv_desc,
dsv.GetAddressOf())))
{
Log_ErrorPrintf("CreateDepthStencilView() failed: %08X", hr);
return {};
}
}
}
return std::unique_ptr<GPUFramebuffer>(
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<GPUFramebuffer>(new D3D11Framebuffer(RT, DS, RT ? RT->GetWidth() : DS->GetWidth(),
RT ? RT->GetHeight() : DS->GetHeight(), std::move(rtv),
std::move(dsv)));
}
D3D11Sampler::D3D11Sampler(ComPtr<ID3D11SamplerState> 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)

View File

@ -306,9 +306,7 @@ public:
void ClearDepth(GPUTexture* t, float d) override;
void InvalidateRenderTarget(GPUTexture* t) override;
std::unique_ptr<GPUFramebuffer> 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<GPUFramebuffer> CreateFramebuffer(GPUTexture* rt_or_ds, GPUTexture* ds = nullptr) override;
std::unique_ptr<GPUShader> CreateShaderFromBinary(GPUShaderStage stage, gsl::span<const u8> data) override;
std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShaderStage stage, const std::string_view& source,

View File

@ -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<GPUShader> GPUDevice::CreateShaderFromBinary(GPUShaderStage stage, gsl::span<const u8> data)
{
// TODO: REMOVE ME
UnreachableCode();
return {};
}
std::unique_ptr<GPUShader> GPUDevice::CreateShaderFromSource(GPUShaderStage stage, const std::string_view& source,
std::vector<u8>* out_binary /* = nullptr */)
{
// TODO: REMOVE ME
UnreachableCode();
return {};
}
std::unique_ptr<GPUPipeline> 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<GPUSampler> GPUDevice::CreateSampler(const GPUSampler::Config& config)
{
// TODO: REMOVE ME
UnreachableCode();
return {};
}
std::unique_ptr<GPUTextureBuffer> GPUDevice::CreateTextureBuffer(GPUTextureBuffer::Format format, u32 size_in_elements)
{
// TODO: REMOVE ME
UnreachableCode();
return {};
}
std::unique_ptr<GPUFramebuffer> 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<GPUShader> GPUDevice::CreateShader(GPUShaderStage stage, const std::string_view& source)
{
std::unique_ptr<GPUShader> shader;
@ -1646,7 +1438,8 @@ std::unique_ptr<GPUDevice> GPUDevice::CreateDeviceForAPI(RenderAPI api)
{
#ifdef WITH_VULKAN
case RenderAPI::Vulkan:
return std::make_unique<VulkanGPUDevice>();
// return std::make_unique<VulkanGPUDevice>();
return {};
#endif
#ifdef WITH_OPENGL
@ -1657,7 +1450,8 @@ std::unique_ptr<GPUDevice> GPUDevice::CreateDeviceForAPI(RenderAPI api)
#ifdef _WIN32
case RenderAPI::D3D12:
return std::make_unique<D3D12GPUDevice>();
// return std::make_unique<D3D12GPUDevice>();
return {};
case RenderAPI::D3D11:
return std::make_unique<D3D11Device>();

View File

@ -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<GPUTexture> 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<GPUSampler> CreateSampler(const GPUSampler::Config& config);
virtual std::unique_ptr<GPUTextureBuffer> CreateTextureBuffer(GPUTextureBuffer::Format format, u32 size_in_elements);
virtual std::unique_ptr<GPUSampler> CreateSampler(const GPUSampler::Config& config) = 0;
virtual std::unique_ptr<GPUTextureBuffer> 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<GPUFramebuffer> 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<GPUFramebuffer> CreateFramebuffer(GPUTexture* rt_or_ds, GPUTexture* ds = nullptr) = 0;
/// Shader abstraction.
// TODO: entry point? source format?
std::unique_ptr<GPUShader> CreateShader(GPUShaderStage stage, const std::string_view& source);
virtual std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config);
virtual std::unique_ptr<GPUPipeline> 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<GPUShader> CreateShaderFromBinary(GPUShaderStage stage, gsl::span<const u8> data);
virtual std::unique_ptr<GPUShader> CreateShaderFromBinary(GPUShaderStage stage, gsl::span<const u8> data) = 0;
virtual std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShaderStage stage, const std::string_view& source,
std::vector<u8>* out_binary = nullptr);
std::vector<u8>* out_binary = nullptr) = 0;
bool AcquireWindow(bool recreate_window);

View File

@ -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<u32>& texture_data,
u32& texture_data_stride, GPUTexture::Format format)
{

View File

@ -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<u32>& texture_data, u32& texture_data_stride,
GPUTexture::Format format);

View File

@ -212,9 +212,7 @@ public:
void ClearDepth(GPUTexture* t, float d) override;
void InvalidateRenderTarget(GPUTexture* t) override;
std::unique_ptr<GPUFramebuffer> 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<GPUFramebuffer> CreateFramebuffer(GPUTexture* rt_or_ds, GPUTexture* ds = nullptr) override;
std::unique_ptr<GPUShader> CreateShaderFromBinary(GPUShaderStage stage, gsl::span<const u8> data) override;
std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShaderStage stage, const std::string_view& source,

View File

@ -970,15 +970,15 @@ std::unique_ptr<GPUTexture> 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<u8>(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<u8>(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<GPUFramebuffer> MetalDevice::CreateFramebuffer(GPUTexture* rt, u32 rt_layer, u32 rt_level,
GPUTexture* ds, u32 ds_layer, u32 ds_level)
std::unique_ptr<GPUFramebuffer> 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<MetalTexture*>((rt_or_ds && rt_or_ds->IsDepthStencil()) ? nullptr : rt_or_ds);
MetalTexture* DS = static_cast<MetalTexture*>((rt_or_ds && rt_or_ds->IsDepthStencil()) ? rt_or_ds : ds);
@autoreleasepool
{
MTLRenderPassDescriptor* desc = [[MTLRenderPassDescriptor renderPassDescriptor] retain];
id<MTLTexture> rt_tex = rt ? [static_cast<MetalTexture*>(rt)->GetMTLTexture() retain] : nil;
id<MTLTexture> ds_tex = ds ? [static_cast<MetalTexture*>(ds)->GetMTLTexture() retain] : nil;
id<MTLTexture> rt_tex = RT ? [RT->GetMTLTexture() retain] : nil;
id<MTLTexture> 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<GPUFramebuffer> 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<GPUFramebuffer> 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<GPUFramebuffer>(new MetalFramebuffer(rt, ds, width, height, rt_tex, ds_tex, desc));
return std::unique_ptr<GPUFramebuffer>(new MetalFramebuffer(RT, DS, width, height, rt_tex, ds_tex, desc));
}
}

View File

@ -47,7 +47,7 @@ std::unique_ptr<GPUTexture> OpenGLDevice::CreateTexture(u32 width, u32 height, u
const void* data, u32 data_stride, bool dynamic /* = false */)
{
std::unique_ptr<OpenGLTexture> tex(std::make_unique<OpenGLTexture>());
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;

View File

@ -69,9 +69,7 @@ public:
void ClearDepth(GPUTexture* t, float d) override;
void InvalidateRenderTarget(GPUTexture* t) override;
std::unique_ptr<GPUFramebuffer> 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<GPUFramebuffer> CreateFramebuffer(GPUTexture* rt_or_ds, GPUTexture* ds = nullptr) override;
std::unique_ptr<GPUShader> CreateShaderFromBinary(GPUShaderStage stage, gsl::span<const u8> data) override;
std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShaderStage stage, const std::string_view& source,

View File

@ -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<u8>(layers);
m_levels = static_cast<u8>(levels);
m_samples = static_cast<u8>(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<u16>(width);
m_height = static_cast<u16>(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<GPUFramebuffer> OpenGLDevice::CreateFramebuffer(GPUTexture* rt, u32 rt_layer, u32 rt_level,
GPUTexture* ds, u32 ds_layer, u32 ds_level)
std::unique_ptr<GPUFramebuffer> OpenGLDevice::CreateFramebuffer(GPUTexture* rt_or_ds, GPUTexture* ds /* = nullptr */)
{
glGetError();
@ -467,34 +402,25 @@ std::unique_ptr<GPUFramebuffer> OpenGLDevice::CreateFramebuffer(GPUTexture* rt,
glGenFramebuffers(1, &fbo_id);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
OpenGLTexture* RT = static_cast<OpenGLTexture*>(rt);
OpenGLTexture* DS = static_cast<OpenGLTexture*>(ds);
DebugAssert((rt_or_ds || ds) && (!rt_or_ds || rt_or_ds->IsRenderTarget() || (rt_or_ds->IsDepthStencil() && !ds)));
OpenGLTexture* RT = static_cast<OpenGLTexture*>((rt_or_ds && rt_or_ds->IsDepthStencil()) ? nullptr : rt_or_ds);
OpenGLTexture* DS = static_cast<OpenGLTexture*>((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<GPUFramebuffer>(
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<GPUFramebuffer>(new OpenGLFramebuffer(RT, DS, RT ? RT->GetWidth() : DS->GetWidth(),
RT ? RT->GetHeight() : DS->GetHeight(), fbo_id));
}
void OpenGLDevice::CommitClear(OpenGLTexture* tex)

View File

@ -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;

View File

@ -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;
}