Merge pull request #6315 from stenzek/abstract-framebuffers

Abstract Framebuffers
This commit is contained in:
Stenzek
2018-03-08 00:52:49 +10:00
committed by GitHub
41 changed files with 1160 additions and 136 deletions
+163 -22
View File
@@ -43,42 +43,84 @@ DXGI_FORMAT GetDXGIFormatForHostFormat(AbstractTextureFormat format)
return DXGI_FORMAT_R8G8B8A8_UNORM;
case AbstractTextureFormat::BGRA8:
return DXGI_FORMAT_B8G8R8A8_UNORM;
case AbstractTextureFormat::R16:
return DXGI_FORMAT_R16_UNORM;
case AbstractTextureFormat::R32F:
return DXGI_FORMAT_R32_FLOAT;
case AbstractTextureFormat::D16:
return DXGI_FORMAT_R16_TYPELESS;
case AbstractTextureFormat::D32F:
return DXGI_FORMAT_R32_TYPELESS;
case AbstractTextureFormat::D32F_S8:
return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
default:
PanicAlert("Unhandled texture format.");
return DXGI_FORMAT_R8G8B8A8_UNORM;
}
}
DXGI_FORMAT GetSRVFormatForHostFormat(AbstractTextureFormat format)
{
switch (format)
{
case AbstractTextureFormat::D16:
return DXGI_FORMAT_R16_UNORM;
case AbstractTextureFormat::D32F:
return DXGI_FORMAT_R32_FLOAT;
case AbstractTextureFormat::D32F_S8:
return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
default:
return GetDXGIFormatForHostFormat(format);
}
}
DXGI_FORMAT GetDSVFormatForHostFormat(AbstractTextureFormat format)
{
switch (format)
{
case AbstractTextureFormat::D16:
return DXGI_FORMAT_D16_UNORM;
case AbstractTextureFormat::D32F:
return DXGI_FORMAT_D32_FLOAT;
case AbstractTextureFormat::D32F_S8:
return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
default:
return GetDXGIFormatForHostFormat(format);
}
}
} // Anonymous namespace
DXTexture::DXTexture(const TextureConfig& tex_config) : AbstractTexture(tex_config)
{
DXGI_FORMAT dxgi_format = GetDXGIFormatForHostFormat(m_config.format);
if (m_config.rendertarget)
DXGI_FORMAT tex_format = GetDXGIFormatForHostFormat(m_config.format);
DXGI_FORMAT srv_format = GetSRVFormatForHostFormat(m_config.format);
DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN;
DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN;
UINT bind_flags = D3D11_BIND_SHADER_RESOURCE;
if (tex_config.rendertarget)
{
m_texture = D3DTexture2D::Create(
m_config.width, m_config.height,
(D3D11_BIND_FLAG)((int)D3D11_BIND_RENDER_TARGET | (int)D3D11_BIND_SHADER_RESOURCE),
D3D11_USAGE_DEFAULT, dxgi_format, 1, m_config.layers);
if (IsDepthFormat(tex_config.format))
{
bind_flags |= D3D11_BIND_DEPTH_STENCIL;
dsv_format = GetDSVFormatForHostFormat(m_config.format);
}
else
{
bind_flags |= D3D11_BIND_RENDER_TARGET;
rtv_format = tex_format;
}
}
else
{
const D3D11_TEXTURE2D_DESC texdesc =
CD3D11_TEXTURE2D_DESC(dxgi_format, m_config.width, m_config.height, 1, m_config.levels,
D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0);
ID3D11Texture2D* pTexture;
const HRESULT hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &pTexture);
CHECK(SUCCEEDED(hr), "Create texture of the TextureCache");
CD3D11_TEXTURE2D_DESC texdesc(tex_format, tex_config.width, tex_config.height, tex_config.layers,
tex_config.levels, bind_flags, D3D11_USAGE_DEFAULT, 0,
tex_config.samples, 0, 0);
m_texture = new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE);
ID3D11Texture2D* pTexture;
HRESULT hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &pTexture);
CHECK(SUCCEEDED(hr), "Create backing DXTexture");
// TODO: better debug names
D3D::SetDebugObjectName(m_texture->GetTex(), "a texture of the TextureCache");
D3D::SetDebugObjectName(m_texture->GetSRV(),
"shader resource view of a texture of the TextureCache");
m_texture = new D3DTexture2D(pTexture, static_cast<D3D11_BIND_FLAG>(bind_flags), srv_format,
dsv_format, rtv_format, tex_config.samples > 1);
SAFE_RELEASE(pTexture);
}
SAFE_RELEASE(pTexture);
}
DXTexture::~DXTexture()
@@ -144,10 +186,25 @@ void DXTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
VertexShaderCache::GetSimpleInputLayout(),
GeometryShaderCache::GetCopyGeometryShader(), 1.0, 0);
FramebufferManager::BindEFBRenderTarget();
g_renderer->RestoreAPIState();
}
void DXTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
u32 layer, u32 level)
{
const DXTexture* srcentry = static_cast<const DXTexture*>(src);
_dbg_assert_(VIDEO, m_config.samples > 1 && m_config.width == srcentry->m_config.width &&
m_config.height == srcentry->m_config.height && m_config.samples == 1);
_dbg_assert_(VIDEO,
rect.left + rect.GetWidth() <= static_cast<int>(srcentry->m_config.width) &&
rect.top + rect.GetHeight() <= static_cast<int>(srcentry->m_config.height));
D3D::context->ResolveSubresource(
m_texture->GetTex(), D3D11CalcSubresource(level, layer, m_config.levels),
srcentry->m_texture->GetTex(), D3D11CalcSubresource(level, layer, srcentry->m_config.levels),
GetDXGIFormatForHostFormat(m_config.format));
}
void DXTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
size_t buffer_size)
{
@@ -287,4 +344,88 @@ void DXStagingTexture::Flush()
m_needs_flush = false;
}
DXFramebuffer::DXFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
u32 width, u32 height, u32 layers, u32 samples,
ID3D11RenderTargetView* rtv, ID3D11DepthStencilView* dsv)
: AbstractFramebuffer(color_format, depth_format, width, height, layers, samples), m_rtv(rtv),
m_dsv(dsv)
{
}
DXFramebuffer::~DXFramebuffer()
{
if (m_rtv)
m_rtv->Release();
if (m_dsv)
m_dsv->Release();
}
std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(const DXTexture* color_attachment,
const DXTexture* depth_attachment)
{
if (!ValidateConfig(color_attachment, depth_attachment))
return nullptr;
const AbstractTextureFormat color_format =
color_attachment ? color_attachment->GetFormat() : AbstractTextureFormat::Undefined;
const AbstractTextureFormat depth_format =
depth_attachment ? depth_attachment->GetFormat() : AbstractTextureFormat::Undefined;
const DXTexture* either_attachment = color_attachment ? color_attachment : depth_attachment;
const u32 width = either_attachment->GetWidth();
const u32 height = either_attachment->GetHeight();
const u32 layers = either_attachment->GetLayers();
const u32 samples = either_attachment->GetSamples();
ID3D11RenderTargetView* rtv = nullptr;
if (color_attachment)
{
D3D11_RENDER_TARGET_VIEW_DESC desc;
desc.Format = GetDXGIFormatForHostFormat(color_attachment->GetConfig().format);
if (color_attachment->GetConfig().IsMultisampled())
{
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
desc.Texture2DMSArray.ArraySize = color_attachment->GetConfig().layers;
desc.Texture2DMSArray.FirstArraySlice = 0;
}
else
{
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
desc.Texture2DArray.ArraySize = color_attachment->GetConfig().layers;
desc.Texture2DArray.FirstArraySlice = 0;
desc.Texture2DArray.MipSlice = 0;
}
HRESULT hr = D3D::device->CreateRenderTargetView(
color_attachment->GetRawTexIdentifier()->GetTex(), &desc, &rtv);
CHECK(SUCCEEDED(hr), "Create render target view for framebuffer");
}
ID3D11DepthStencilView* dsv = nullptr;
if (depth_attachment)
{
D3D11_DEPTH_STENCIL_VIEW_DESC desc;
desc.Format = GetDXGIFormatForHostFormat(depth_attachment->GetConfig().format);
if (depth_attachment->GetConfig().IsMultisampled())
{
desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
desc.Texture2DMSArray.ArraySize = depth_attachment->GetConfig().layers;
desc.Texture2DMSArray.FirstArraySlice = 0;
}
else
{
desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
desc.Texture2DArray.ArraySize = depth_attachment->GetConfig().layers;
desc.Texture2DArray.FirstArraySlice = 0;
desc.Texture2DArray.MipSlice = 0;
}
HRESULT hr = D3D::device->CreateDepthStencilView(
depth_attachment->GetRawTexIdentifier()->GetTex(), &desc, &dsv);
CHECK(SUCCEEDED(hr), "Create depth stencil view for framebuffer");
}
return std::make_unique<DXFramebuffer>(color_format, depth_format, width, height, layers, samples,
rtv, dsv);
}
} // namespace DX11
+23
View File
@@ -4,8 +4,10 @@
#pragma once
#include <memory>
#include "Common/CommonTypes.h"
#include "VideoCommon/AbstractFramebuffer.h"
#include "VideoCommon/AbstractStagingTexture.h"
#include "VideoCommon/AbstractTexture.h"
@@ -26,6 +28,8 @@ public:
void ScaleRectangleFromTexture(const AbstractTexture* source,
const MathUtil::Rectangle<int>& srcrect,
const MathUtil::Rectangle<int>& dstrect) override;
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
u32 layer, u32 level) override;
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
size_t buffer_size) override;
@@ -61,4 +65,23 @@ private:
ID3D11Texture2D* m_tex = nullptr;
};
class DXFramebuffer final : public AbstractFramebuffer
{
public:
DXFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width,
u32 height, u32 layers, u32 samples, ID3D11RenderTargetView* rtv,
ID3D11DepthStencilView* dsv);
~DXFramebuffer() override;
ID3D11RenderTargetView* const* GetRTVArray() const { return &m_rtv; }
UINT GetNumRTVs() const { return m_rtv ? 1 : 0; }
ID3D11DepthStencilView* GetDSV() const { return m_dsv; }
static std::unique_ptr<DXFramebuffer> Create(const DXTexture* color_attachment,
const DXTexture* depth_attachment);
protected:
ID3D11RenderTargetView* m_rtv;
ID3D11DepthStencilView* m_dsv;
};
} // namespace DX11
@@ -87,9 +87,7 @@ D3DTexture2D*& FramebufferManager::GetResolvedEFBDepthTexture()
PixelShaderCache::GetDepthResolveProgram(), VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader());
BindEFBRenderTarget();
g_renderer->RestoreAPIState();
return m_efb.resolved_depth_tex;
}
else
@@ -43,7 +43,7 @@ PSTextureEncoder::~PSTextureEncoder() = default;
void PSTextureEncoder::Init()
{
// TODO: Move this to a constant somewhere in common.
TextureConfig encoding_texture_config(EFB_WIDTH * 4, 1024, 1, 1, AbstractTextureFormat::BGRA8,
TextureConfig encoding_texture_config(EFB_WIDTH * 4, 1024, 1, 1, 1, AbstractTextureFormat::BGRA8,
true);
m_encoding_render_texture = g_renderer->CreateTexture(encoding_texture_config);
m_encoding_readback_texture =
@@ -131,8 +131,6 @@ void PSTextureEncoder::Encode(u8* dst, const EFBCopyParams& params, u32 native_w
}
}
// Restore API
FramebufferManager::BindEFBRenderTarget();
g_renderer->RestoreAPIState();
}
+48 -7
View File
@@ -90,6 +90,8 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height)
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)m_target_width, (float)m_target_height);
D3D::context->RSSetViewports(1, &vp);
FramebufferManager::BindEFBRenderTarget();
m_current_framebuffer_width = m_target_width;
m_current_framebuffer_height = m_target_height;
}
Renderer::~Renderer()
@@ -243,6 +245,14 @@ std::unique_ptr<AbstractStagingTexture> Renderer::CreateStagingTexture(StagingTe
return DXStagingTexture::Create(type, config);
}
std::unique_ptr<AbstractFramebuffer>
Renderer::CreateFramebuffer(const AbstractTexture* color_attachment,
const AbstractTexture* depth_attachment)
{
return DXFramebuffer::Create(static_cast<const DXTexture*>(color_attachment),
static_cast<const DXTexture*>(depth_attachment));
}
void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
{
D3D::DrawTextScaled(static_cast<float>(left + 1), static_cast<float>(top + 1), 20.f, 0.0f,
@@ -450,7 +460,6 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
VertexShaderCache::GetSimpleInputLayout());
// Restore expected game state.
FramebufferManager::BindEFBRenderTarget();
RestoreAPIState();
// Copy the pixel from the renderable to cpu-readable buffer.
@@ -525,7 +534,6 @@ void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num
D3D11_VIEWPORT vp =
CD3D11_VIEWPORT(0.0f, 0.0f, (float)GetTargetWidth(), (float)GetTargetHeight());
D3D::context->RSSetViewports(1, &vp);
FramebufferManager::BindEFBRenderTarget(false);
}
else // if (type == EFBAccessType::PokeZ)
{
@@ -536,7 +544,6 @@ void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num
CD3D11_VIEWPORT(0.0f, 0.0f, (float)GetTargetWidth(), (float)GetTargetHeight());
D3D::context->RSSetViewports(1, &vp);
FramebufferManager::BindEFBRenderTarget();
}
D3D::DrawEFBPokeQuads(type, points, num_points);
@@ -627,10 +634,8 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
GetTargetHeight(), pixel_shader, VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader());
RestoreAPIState();
FramebufferManager::SwapReinterpretTexture();
FramebufferManager::BindEFBRenderTarget();
RestoreAPIState();
}
void Renderer::SetBlendingState(const BlendingState& state)
@@ -653,6 +658,9 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
static constexpr std::array<float, 4> clear_color{{0.f, 0.f, 0.f, 1.f}};
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), nullptr);
D3D::context->ClearRenderTargetView(D3D::GetBackBuffer()->GetRTV(), clear_color.data());
m_current_framebuffer = nullptr;
m_current_framebuffer_width = m_backbuffer_width;
m_current_framebuffer_height = m_backbuffer_height;
// activate linear filtering for the buffer copies
D3D::SetLinearCopySampler();
@@ -707,7 +715,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
// begin next frame
RestoreAPIState();
FramebufferManager::BindEFBRenderTarget();
}
void Renderer::CheckForSurfaceChange()
@@ -769,6 +776,10 @@ void Renderer::ResetAPIState()
void Renderer::RestoreAPIState()
{
// Gets us back into a more game-like state.
m_current_framebuffer = nullptr;
m_current_framebuffer_width = m_target_width;
m_current_framebuffer_height = m_target_height;
FramebufferManager::BindEFBRenderTarget();
BPFunctions::SetViewport();
BPFunctions::SetScissor();
}
@@ -797,6 +808,36 @@ void Renderer::RestoreState()
{
}
void Renderer::SetFramebuffer(const AbstractFramebuffer* framebuffer)
{
const DXFramebuffer* fb = static_cast<const DXFramebuffer*>(framebuffer);
D3D::context->OMSetRenderTargets(fb->GetNumRTVs(), fb->GetRTVArray(), fb->GetDSV());
m_current_framebuffer = fb;
m_current_framebuffer_width = fb->GetWidth();
m_current_framebuffer_height = fb->GetHeight();
}
void Renderer::SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer)
{
SetFramebuffer(framebuffer);
}
void Renderer::SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
const ClearColor& color_value, float depth_value)
{
SetFramebuffer(framebuffer);
if (framebuffer->GetColorFormat() != AbstractTextureFormat::Undefined)
{
D3D::context->ClearRenderTargetView(
static_cast<const DXFramebuffer*>(framebuffer)->GetRTVArray()[0], color_value.data());
}
if (framebuffer->GetDepthFormat() != AbstractTextureFormat::Undefined)
{
D3D::context->ClearDepthStencilView(static_cast<const DXFramebuffer*>(framebuffer)->GetDSV(),
D3D11_CLEAR_DEPTH, depth_value, 0);
}
}
void Renderer::SetRasterizationState(const RasterizationState& state)
{
m_gx_state.raster.hex = state.hex;
+8
View File
@@ -31,8 +31,16 @@ public:
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(const AbstractTexture* color_attachment,
const AbstractTexture* depth_attachment) override;
void SetPipeline(const AbstractPipeline* pipeline) override;
void SetFramebuffer(const AbstractFramebuffer* framebuffer) override;
void SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer) override;
void SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
const ClearColor& color_value = {},
float depth_value = 0.0f) override;
void SetBlendingState(const BlendingState& state) override;
void SetScissorRect(const MathUtil::Rectangle<int>& rc) override;
void SetRasterizationState(const RasterizationState& state) override;
@@ -160,7 +160,6 @@ void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(),
GeometryShaderCache::GetCopyGeometryShader());
FramebufferManager::BindEFBRenderTarget();
g_renderer->RestoreAPIState();
}
@@ -275,7 +274,6 @@ void TextureCache::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy,
pixel_shader, VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader());
FramebufferManager::BindEFBRenderTarget();
g_renderer->RestoreAPIState();
}
@@ -21,6 +21,10 @@ void NullTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
const MathUtil::Rectangle<int>& dstrect)
{
}
void NullTexture::ResolveFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& rect, u32 layer, u32 level)
{
}
void NullTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
size_t buffer_size)
@@ -66,4 +70,31 @@ void NullStagingTexture::Flush()
m_needs_flush = false;
}
NullFramebuffer::NullFramebuffer(AbstractTextureFormat color_format,
AbstractTextureFormat depth_format, u32 width, u32 height,
u32 layers, u32 samples)
: AbstractFramebuffer(color_format, depth_format, width, height, layers, samples)
{
}
std::unique_ptr<NullFramebuffer> NullFramebuffer::Create(const NullTexture* color_attachment,
const NullTexture* depth_attachment)
{
if (!ValidateConfig(color_attachment, depth_attachment))
return nullptr;
const AbstractTextureFormat color_format =
color_attachment ? color_attachment->GetFormat() : AbstractTextureFormat::Undefined;
const AbstractTextureFormat depth_format =
depth_attachment ? depth_attachment->GetFormat() : AbstractTextureFormat::Undefined;
const NullTexture* either_attachment = color_attachment ? color_attachment : depth_attachment;
const u32 width = either_attachment->GetWidth();
const u32 height = either_attachment->GetHeight();
const u32 layers = either_attachment->GetLayers();
const u32 samples = either_attachment->GetSamples();
return std::make_unique<NullFramebuffer>(color_format, depth_format, width, height, layers,
samples);
}
} // namespace Null
@@ -4,10 +4,12 @@
#pragma once
#include <memory>
#include <vector>
#include "Common/CommonTypes.h"
#include "VideoCommon/AbstractFramebuffer.h"
#include "VideoCommon/AbstractStagingTexture.h"
#include "VideoCommon/AbstractTexture.h"
@@ -26,6 +28,8 @@ public:
void ScaleRectangleFromTexture(const AbstractTexture* source,
const MathUtil::Rectangle<int>& srcrect,
const MathUtil::Rectangle<int>& dstrect) override;
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
u32 layer, u32 level) override;
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
size_t buffer_size) override;
};
@@ -51,4 +55,15 @@ private:
std::vector<u8> m_texture_buf;
};
class NullFramebuffer final : public AbstractFramebuffer
{
public:
explicit NullFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
u32 width, u32 height, u32 layers, u32 samples);
~NullFramebuffer() override = default;
static std::unique_ptr<NullFramebuffer> Create(const NullTexture* color_attachment,
const NullTexture* depth_attachment);
};
} // namespace Null
@@ -69,6 +69,14 @@ std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelin
return std::make_unique<NullPipeline>();
}
std::unique_ptr<AbstractFramebuffer>
Renderer::CreateFramebuffer(const AbstractTexture* color_attachment,
const AbstractTexture* depth_attachment)
{
return NullFramebuffer::Create(static_cast<const NullTexture*>(color_attachment),
static_cast<const NullTexture*>(depth_attachment));
}
void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
{
NOTICE_LOG(VIDEO, "RenderText: %s", text.c_str());
+3
View File
@@ -17,6 +17,9 @@ public:
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(const AbstractTexture* color_attachment,
const AbstractTexture* depth_attachment) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
size_t length) override;
+184 -52
View File
@@ -35,6 +35,16 @@ GLenum GetGLInternalFormatForTextureFormat(AbstractTextureFormat format, bool st
return storage ? GL_RGBA8 : GL_RGBA;
case AbstractTextureFormat::BGRA8:
return storage ? GL_RGBA8 : GL_BGRA;
case AbstractTextureFormat::R16:
return GL_R16;
case AbstractTextureFormat::R32F:
return GL_R32F;
case AbstractTextureFormat::D16:
return GL_DEPTH_COMPONENT16;
case AbstractTextureFormat::D32F:
return GL_DEPTH_COMPONENT32F;
case AbstractTextureFormat::D32F_S8:
return GL_DEPTH32F_STENCIL8;
default:
PanicAlert("Unhandled texture format.");
return storage ? GL_RGBA8 : GL_RGBA;
@@ -49,6 +59,14 @@ GLenum GetGLFormatForTextureFormat(AbstractTextureFormat format)
return GL_RGBA;
case AbstractTextureFormat::BGRA8:
return GL_BGRA;
case AbstractTextureFormat::R16:
case AbstractTextureFormat::R32F:
return GL_RED;
case AbstractTextureFormat::D16:
case AbstractTextureFormat::D32F:
return GL_DEPTH_COMPONENT;
case AbstractTextureFormat::D32F_S8:
return GL_DEPTH_STENCIL;
// Compressed texture formats don't use this parameter.
default:
return GL_UNSIGNED_BYTE;
@@ -62,6 +80,16 @@ GLenum GetGLTypeForTextureFormat(AbstractTextureFormat format)
case AbstractTextureFormat::RGBA8:
case AbstractTextureFormat::BGRA8:
return GL_UNSIGNED_BYTE;
case AbstractTextureFormat::R16:
return GL_UNSIGNED_SHORT;
case AbstractTextureFormat::R32F:
return GL_FLOAT;
case AbstractTextureFormat::D16:
return GL_UNSIGNED_SHORT;
case AbstractTextureFormat::D32F:
return GL_FLOAT;
case AbstractTextureFormat::D32F_S8:
return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
// Compressed texture formats don't use this parameter.
default:
return GL_UNSIGNED_BYTE;
@@ -80,38 +108,50 @@ bool UsePersistentStagingBuffers()
OGLTexture::OGLTexture(const TextureConfig& tex_config) : AbstractTexture(tex_config)
{
_dbg_assert_msg_(VIDEO, !tex_config.IsMultisampled() || tex_config.levels == 1,
"OpenGL does not support multisampled textures with mip levels");
GLenum target =
tex_config.IsMultisampled() ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY;
glGenTextures(1, &m_texId);
glActiveTexture(GL_TEXTURE9);
glBindTexture(GL_TEXTURE_2D_ARRAY, m_texId);
glBindTexture(target, m_texId);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, m_config.levels - 1);
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, m_config.levels - 1);
if (g_ogl_config.bSupportsTextureStorage)
GLenum gl_internal_format = GetGLInternalFormatForTextureFormat(m_config.format, true);
if (tex_config.IsMultisampled())
{
GLenum gl_internal_format = GetGLInternalFormatForTextureFormat(m_config.format, true);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, m_config.levels, gl_internal_format, m_config.width,
m_config.height, m_config.layers);
if (g_ogl_config.bSupportsTextureStorage)
glTexStorage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width,
m_config.height, m_config.layers, GL_FALSE);
else
glTexImage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width,
m_config.height, m_config.layers, GL_FALSE);
}
else if (g_ogl_config.bSupportsTextureStorage)
{
glTexStorage3D(target, m_config.levels, gl_internal_format, m_config.width, m_config.height,
m_config.layers);
}
if (m_config.rendertarget)
{
// We can't render to compressed formats.
_assert_(!IsCompressedFormat(m_config.format));
if (!g_ogl_config.bSupportsTextureStorage)
if (!g_ogl_config.bSupportsTextureStorage && !tex_config.IsMultisampled())
{
for (u32 level = 0; level < m_config.levels; level++)
{
glTexImage3D(GL_TEXTURE_2D_ARRAY, level, GL_RGBA, std::max(m_config.width >> level, 1u),
glTexImage3D(target, level, GL_RGBA, std::max(m_config.width >> level, 1u),
std::max(m_config.height >> level, 1u), m_config.layers, 0, GL_RGBA,
GL_UNSIGNED_BYTE, nullptr);
}
}
glGenFramebuffers(1, &m_framebuffer);
FramebufferManager::SetFramebuffer(m_framebuffer);
FramebufferManager::FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D_ARRAY, m_texId, 0);
FramebufferManager::FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, m_texId,
0);
// We broke the framebuffer binding here, and need to restore it, as the CreateTexture
// method is in the base renderer class and can be called by VideoCommon.
@@ -156,47 +196,60 @@ void OGLTexture::CopyRectangleFromTexture(const AbstractTexture* src,
}
else
{
// If it isn't a single leveled/layered texture, we need to update the framebuffer.
bool update_src_framebuffer =
srcentry->m_framebuffer == 0 || srcentry->m_config.layers != 0 || src_level != 0;
bool update_dst_framebuffer = m_framebuffer == 0 || m_config.layers != 0 || dst_level != 0;
if (!m_framebuffer)
glGenFramebuffers(1, &m_framebuffer);
if (!srcentry->m_framebuffer)
glGenFramebuffers(1, &const_cast<OGLTexture*>(srcentry)->m_framebuffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcentry->m_framebuffer);
if (update_src_framebuffer)
{
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcentry->m_texId,
src_level, src_layer);
}
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer);
if (update_dst_framebuffer)
{
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texId, dst_level,
dst_layer);
}
glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, dst_rect.left,
dst_rect.top, dst_rect.right, dst_rect.bottom, GL_COLOR_BUFFER_BIT,
GL_NEAREST);
if (update_src_framebuffer)
{
FramebufferManager::FramebufferTexture(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D_ARRAY, srcentry->m_texId, 0);
}
if (update_dst_framebuffer)
{
FramebufferManager::FramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D_ARRAY, m_texId, 0);
}
FramebufferManager::SetFramebuffer(0);
BlitFramebuffer(const_cast<OGLTexture*>(srcentry), src_rect, src_layer, src_level, dst_rect,
dst_layer, dst_level);
}
}
void OGLTexture::BlitFramebuffer(OGLTexture* srcentry, const MathUtil::Rectangle<int>& src_rect,
u32 src_layer, u32 src_level,
const MathUtil::Rectangle<int>& dst_rect, u32 dst_layer,
u32 dst_level)
{
// If it isn't a single leveled/layered texture, we need to update the framebuffer.
bool update_src_framebuffer =
srcentry->m_framebuffer == 0 || srcentry->m_config.layers != 0 || src_level != 0;
bool update_dst_framebuffer = m_framebuffer == 0 || m_config.layers != 0 || dst_level != 0;
if (!m_framebuffer)
glGenFramebuffers(1, &m_framebuffer);
if (!srcentry->m_framebuffer)
glGenFramebuffers(1, &const_cast<OGLTexture*>(srcentry)->m_framebuffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcentry->m_framebuffer);
if (update_src_framebuffer)
{
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcentry->m_texId,
src_level, src_layer);
}
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer);
if (update_dst_framebuffer)
{
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texId, dst_level,
dst_layer);
}
glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, dst_rect.left,
dst_rect.top, dst_rect.right, dst_rect.bottom, GL_COLOR_BUFFER_BIT, GL_NEAREST);
if (update_src_framebuffer)
{
FramebufferManager::FramebufferTexture(
GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
srcentry->m_config.IsMultisampled() ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY,
srcentry->m_texId, 0);
}
if (update_dst_framebuffer)
{
FramebufferManager::FramebufferTexture(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
m_config.IsMultisampled() ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY, m_texId,
0);
}
FramebufferManager::SetFramebuffer(0);
}
void OGLTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
const MathUtil::Rectangle<int>& srcrect,
const MathUtil::Rectangle<int>& dstrect)
@@ -219,10 +272,21 @@ void OGLTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
glUniform4f(TextureCache::GetInstance()->GetColorCopyPositionUniform(), float(srcrect.left),
float(srcrect.top), float(srcrect.GetWidth()), float(srcrect.GetHeight()));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
FramebufferManager::SetFramebuffer(0);
g_renderer->RestoreAPIState();
}
void OGLTexture::ResolveFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& rect, u32 layer, u32 level)
{
const OGLTexture* srcentry = static_cast<const OGLTexture*>(src);
_dbg_assert_(VIDEO, m_config.samples > 1 && m_config.width == srcentry->m_config.width &&
m_config.height == srcentry->m_config.height && m_config.samples == 1);
_dbg_assert_(VIDEO,
rect.left + rect.GetWidth() <= static_cast<int>(srcentry->m_config.width) &&
rect.top + rect.GetHeight() <= static_cast<int>(srcentry->m_config.height));
BlitFramebuffer(const_cast<OGLTexture*>(srcentry), rect, layer, level, rect, layer, level);
}
void OGLTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
size_t buffer_size)
{
@@ -529,4 +593,72 @@ void OGLStagingTexture::Unmap()
m_map_pointer = nullptr;
}
OGLFramebuffer::OGLFramebuffer(AbstractTextureFormat color_format,
AbstractTextureFormat depth_format, u32 width, u32 height,
u32 layers, u32 samples, GLuint fbo)
: AbstractFramebuffer(color_format, depth_format, width, height, layers, samples), m_fbo(fbo)
{
}
OGLFramebuffer::~OGLFramebuffer()
{
glDeleteFramebuffers(1, &m_fbo);
}
std::unique_ptr<OGLFramebuffer> OGLFramebuffer::Create(const OGLTexture* color_attachment,
const OGLTexture* depth_attachment)
{
if (!ValidateConfig(color_attachment, depth_attachment))
return nullptr;
const AbstractTextureFormat color_format =
color_attachment ? color_attachment->GetFormat() : AbstractTextureFormat::Undefined;
const AbstractTextureFormat depth_format =
depth_attachment ? depth_attachment->GetFormat() : AbstractTextureFormat::Undefined;
const OGLTexture* either_attachment = color_attachment ? color_attachment : depth_attachment;
const u32 width = either_attachment->GetWidth();
const u32 height = either_attachment->GetHeight();
const u32 layers = either_attachment->GetLayers();
const u32 samples = either_attachment->GetSamples();
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
if (color_attachment)
{
if (color_attachment->GetConfig().layers > 1)
{
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
color_attachment->GetRawTexIdentifier(), 0);
}
else
{
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
color_attachment->GetRawTexIdentifier(), 0, 0);
}
}
if (depth_attachment)
{
GLenum attachment = AbstractTexture::IsStencilFormat(depth_format) ?
GL_DEPTH_STENCIL_ATTACHMENT :
GL_DEPTH_ATTACHMENT;
if (depth_attachment->GetConfig().layers > 1)
{
glFramebufferTexture(GL_FRAMEBUFFER, attachment, depth_attachment->GetRawTexIdentifier(), 0);
}
else
{
glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, depth_attachment->GetRawTexIdentifier(),
0, 0);
}
}
_dbg_assert_(VIDEO, glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
FramebufferManager::SetFramebuffer(0);
return std::make_unique<OGLFramebuffer>(color_format, depth_format, width, height, layers,
samples, fbo);
}
} // namespace OGL
@@ -4,10 +4,12 @@
#pragma once
#include <memory>
#include <vector>
#include "Common/GL/GLUtil.h"
#include "VideoCommon/AbstractFramebuffer.h"
#include "VideoCommon/AbstractStagingTexture.h"
#include "VideoCommon/AbstractTexture.h"
@@ -26,6 +28,8 @@ public:
void ScaleRectangleFromTexture(const AbstractTexture* source,
const MathUtil::Rectangle<int>& srcrect,
const MathUtil::Rectangle<int>& dstrect) override;
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
u32 layer, u32 level) override;
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
size_t buffer_size) override;
@@ -33,6 +37,10 @@ public:
GLuint GetFramebuffer() const;
private:
void BlitFramebuffer(OGLTexture* srcentry, const MathUtil::Rectangle<int>& src_rect,
u32 src_layer, u32 src_level, const MathUtil::Rectangle<int>& dst_rect,
u32 dst_layer, u32 dst_level);
GLuint m_texId;
GLuint m_framebuffer = 0;
};
@@ -68,4 +76,19 @@ private:
GLsync m_fence = 0;
};
class OGLFramebuffer final : public AbstractFramebuffer
{
public:
OGLFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width,
u32 height, u32 layers, u32 samples, GLuint fbo);
~OGLFramebuffer() override;
GLuint GetFBO() const { return m_fbo; }
static std::unique_ptr<OGLFramebuffer> Create(const OGLTexture* color_attachment,
const OGLTexture* depth_attachment);
protected:
GLuint m_fbo;
};
} // namespace OGL
+57 -4
View File
@@ -827,6 +827,8 @@ void Renderer::Init()
// Initialize the FramebufferManager
g_framebuffer_manager = std::make_unique<FramebufferManager>(
m_target_width, m_target_height, s_MSAASamples, BoundingBox::NeedsStencilBuffer());
m_current_framebuffer_width = m_target_width;
m_current_framebuffer_height = m_target_height;
m_post_processor = std::make_unique<OpenGLPostProcessing>();
s_raster_font = std::make_unique<RasterFont>();
@@ -843,6 +845,14 @@ std::unique_ptr<AbstractStagingTexture> Renderer::CreateStagingTexture(StagingTe
return OGLStagingTexture::Create(type, config);
}
std::unique_ptr<AbstractFramebuffer>
Renderer::CreateFramebuffer(const AbstractTexture* color_attachment,
const AbstractTexture* depth_attachment)
{
return OGLFramebuffer::Create(static_cast<const OGLTexture*>(color_attachment),
static_cast<const OGLTexture*>(depth_attachment));
}
void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
{
s_raster_font->printMultilineText(text,
@@ -1145,7 +1155,7 @@ void Renderer::SetViewport(float x, float y, float width, float height, float ne
{
// The x/y parameters here assume a upper-left origin. glViewport takes an offset from the
// lower-left of the framebuffer, so we must set y to the distance from the lower-left.
y = static_cast<float>(m_target_height) - y - height;
y = static_cast<float>(m_current_framebuffer_height) - y - height;
if (g_ogl_config.bSupportViewportFloat)
{
glViewportIndexedf(0, x, y, width, height);
@@ -1238,6 +1248,44 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
}
}
void Renderer::SetFramebuffer(const AbstractFramebuffer* framebuffer)
{
glBindFramebuffer(GL_FRAMEBUFFER, static_cast<const OGLFramebuffer*>(framebuffer)->GetFBO());
m_current_framebuffer = framebuffer;
m_current_framebuffer_width = framebuffer->GetWidth();
m_current_framebuffer_height = framebuffer->GetHeight();
}
void Renderer::SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer)
{
// EXT_discard_framebuffer could be used here to save bandwidth on tilers.
SetFramebuffer(framebuffer);
}
void Renderer::SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
const ClearColor& color_value, float depth_value)
{
SetFramebuffer(framebuffer);
// NOTE: This disturbs the current scissor/mask setting.
// This won't be an issue when we implement proper state tracking.
glDisable(GL_SCISSOR_TEST);
GLbitfield clear_mask = 0;
if (framebuffer->HasColorBuffer())
{
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClearColor(color_value[0], color_value[1], color_value[2], color_value[3]);
clear_mask |= GL_COLOR_BUFFER_BIT;
}
if (framebuffer->HasDepthBuffer())
{
glDepthMask(GL_TRUE);
glClearDepth(depth_value);
clear_mask |= GL_DEPTH_BUFFER_BIT;
}
glClear(clear_mask);
}
void Renderer::ApplyBlendingState(const BlendingState& state)
{
bool useDualSource =
@@ -1351,6 +1399,9 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_current_framebuffer = nullptr;
m_current_framebuffer_width = m_backbuffer_width;
m_current_framebuffer_height = m_backbuffer_height;
// Copy the framebuffer to screen.
BlitScreen(sourceRc, flipped_trc, xfb_texture->GetRawTexIdentifier(),
@@ -1416,9 +1467,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
g_texture_cache->Cleanup(frameCount);
ProgramShaderCache::RetrieveAsyncShaders();
// Render to the framebuffer.
FramebufferManager::SetFramebuffer(0);
RestoreAPIState();
g_Config.iSaveTargetId = 0;
@@ -1499,6 +1547,11 @@ void Renderer::ResetAPIState()
void Renderer::RestoreAPIState()
{
m_current_framebuffer = nullptr;
m_current_framebuffer_width = m_target_width;
m_current_framebuffer_height = m_target_height;
FramebufferManager::SetFramebuffer(0);
// Gets us back into a more game-like state.
glEnable(GL_SCISSOR_TEST);
if (g_ActiveConfig.backend_info.bSupportsDepthClamp)
+8
View File
@@ -95,8 +95,16 @@ public:
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(const AbstractTexture* color_attachment,
const AbstractTexture* depth_attachment) override;
void SetPipeline(const AbstractPipeline* pipeline) override;
void SetFramebuffer(const AbstractFramebuffer* framebuffer) override;
void SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer) override;
void SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
const ClearColor& color_value = {},
float depth_value = 0.0f) override;
void SetBlendingState(const BlendingState& state) override;
void SetScissorRect(const MathUtil::Rectangle<int>& rc) override;
void SetRasterizationState(const RasterizationState& state) override;
@@ -323,7 +323,6 @@ void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
ProgramShaderCache::BindVertexFormat(nullptr);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
FramebufferManager::SetFramebuffer(0);
g_renderer->RestoreAPIState();
}
@@ -540,7 +539,6 @@ void TextureCache::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy,
ProgramShaderCache::BindVertexFormat(nullptr);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
FramebufferManager::SetFramebuffer(0);
g_renderer->RestoreAPIState();
}
}
@@ -86,7 +86,7 @@ static EncodingProgram& GetOrCreateEncodingShader(const EFBCopyParams& params)
void Init()
{
TextureConfig config(renderBufferWidth, renderBufferHeight, 1, 1, AbstractTextureFormat::BGRA8,
TextureConfig config(renderBufferWidth, renderBufferHeight, 1, 1, 1, AbstractTextureFormat::BGRA8,
true);
s_encoding_render_texture = g_renderer->CreateTexture(config);
s_encoding_readback_texture =
@@ -133,8 +133,6 @@ static void EncodeToRamUsingShader(GLuint srcTexture, u8* destAddr, u32 dst_line
s_encoding_readback_texture->CopyFromTexture(s_encoding_render_texture.get(), copy_rect, 0, 0,
copy_rect);
s_encoding_readback_texture->ReadTexels(copy_rect, destAddr, writeStride);
FramebufferManager::SetFramebuffer(0);
}
void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyParams& params, u32 native_width,
@@ -157,7 +155,6 @@ void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyParams& params, u32 nativ
EncodeToRamUsingShader(read_texture, dest_ptr, bytes_per_row, num_blocks_y, memory_stride,
scale_by_half && !params.depth, params.y_scale);
FramebufferManager::SetFramebuffer(0);
g_renderer->RestoreAPIState();
}
@@ -39,6 +39,14 @@ SWRenderer::CreateStagingTexture(StagingTextureType type, const TextureConfig& c
return std::make_unique<SW::SWStagingTexture>(type, config);
}
std::unique_ptr<AbstractFramebuffer>
SWRenderer::CreateFramebuffer(const AbstractTexture* color_attachment,
const AbstractTexture* depth_attachment)
{
return SW::SWFramebuffer::Create(static_cast<const SW::SWTexture*>(color_attachment),
static_cast<const SW::SWTexture*>(depth_attachment));
}
void SWRenderer::RenderText(const std::string& pstr, int left, int top, u32 color)
{
SWOGLWindow::s_instance->PrintText(pstr, left, top, color);
@@ -16,6 +16,9 @@ public:
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(const AbstractTexture* color_attachment,
const AbstractTexture* depth_attachment) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
size_t length) override;
@@ -86,6 +86,10 @@ void SWTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
memcpy(GetData(), destination_pixels.data(), destination_pixels.size());
}
}
void SWTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
u32 layer, u32 level)
{
}
void SWTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
size_t buffer_size)
@@ -148,4 +152,31 @@ void SWStagingTexture::Flush()
{
m_needs_flush = false;
}
SWFramebuffer::SWFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
u32 width, u32 height, u32 layers, u32 samples)
: AbstractFramebuffer(color_format, depth_format, width, height, layers, samples)
{
}
std::unique_ptr<SWFramebuffer> SWFramebuffer::Create(const SWTexture* color_attachment,
const SWTexture* depth_attachment)
{
if (!ValidateConfig(color_attachment, depth_attachment))
return nullptr;
const AbstractTextureFormat color_format =
color_attachment ? color_attachment->GetFormat() : AbstractTextureFormat::Undefined;
const AbstractTextureFormat depth_format =
depth_attachment ? depth_attachment->GetFormat() : AbstractTextureFormat::Undefined;
const SWTexture* either_attachment = color_attachment ? color_attachment : depth_attachment;
const u32 width = either_attachment->GetWidth();
const u32 height = either_attachment->GetHeight();
const u32 layers = either_attachment->GetLayers();
const u32 samples = either_attachment->GetSamples();
return std::make_unique<SWFramebuffer>(color_format, depth_format, width, height, layers,
samples);
}
} // namespace SW

Some files were not shown because too many files have changed in this diff Show More