mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
Plumb through a parameter for creating framebuffers of different color formats
This commit is contained in:
parent
6c9963bd26
commit
a989b08648
@ -1325,7 +1325,17 @@ Framebuffer *D3D11DrawContext::CreateFramebuffer(const FramebufferDesc &desc) {
|
||||
// Texture arrays are supported but we don't have any other use cases yet.
|
||||
_dbg_assert_(desc.numLayers == 1);
|
||||
|
||||
fb->colorFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
DXGI_FORMAT colorFormat;
|
||||
switch (desc.colorFormat) {
|
||||
case DataFormat::R8G8B8A8_UNORM:
|
||||
colorFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
default:
|
||||
_assert_msg_(false, "Framebuffer format not supported");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
fb->colorFormat = colorFormat;
|
||||
D3D11_TEXTURE2D_DESC descColor{};
|
||||
descColor.Width = desc.width;
|
||||
descColor.Height = desc.height;
|
||||
|
@ -1264,7 +1264,18 @@ Framebuffer *D3D9Context::CreateFramebuffer(const FramebufferDesc &desc) {
|
||||
D3D9Framebuffer *fbo = new D3D9Framebuffer(desc.width, desc.height);
|
||||
fbo->depthstenciltex = nullptr;
|
||||
|
||||
HRESULT rtResult = device_->CreateTexture(desc.width, desc.height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &fbo->tex, nullptr);
|
||||
D3DFORMAT colorFormat;
|
||||
switch (desc.colorFormat) {
|
||||
case DataFormat::R8G8B8A8_UNORM:
|
||||
// We pretend to support this, although in reality we use the reverse format.
|
||||
colorFormat = D3DFMT_A8R8G8B8;
|
||||
break;
|
||||
default:
|
||||
_assert_msg_(false, "Framebuffer format not supported");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HRESULT rtResult = device_->CreateTexture(desc.width, desc.height, 1, D3DUSAGE_RENDERTARGET, colorFormat, D3DPOOL_DEFAULT, &fbo->tex, nullptr);
|
||||
if (FAILED(rtResult)) {
|
||||
ERROR_LOG(G3D, "Failed to create render target");
|
||||
fbo->Release();
|
||||
|
@ -517,7 +517,22 @@ void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) {
|
||||
|
||||
// Color texture is same everywhere
|
||||
glGenFramebuffers(1, &fbo->handle);
|
||||
initFBOTexture(fbo->color_texture, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, true);
|
||||
|
||||
GLint colorInternalFormat;
|
||||
GLint colorFormat;
|
||||
GLint colorElementType;
|
||||
switch (fbo->colorFormat) {
|
||||
case Draw::DataFormat::R8G8B8A8_UNORM:
|
||||
colorInternalFormat = GL_RGBA;
|
||||
colorFormat = GL_RGBA;
|
||||
colorElementType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
default:
|
||||
_assert_msg_(false, "Data format not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
initFBOTexture(fbo->color_texture, colorInternalFormat, colorFormat, colorElementType, true);
|
||||
|
||||
retry_depth:
|
||||
if (!fbo->z_stencil_) {
|
||||
|
@ -106,6 +106,7 @@ void GLDeleter::Perform(GLRenderManager *renderManager, bool skipGLCalls) {
|
||||
framebuffer->z_stencil_texture.texture = 0;
|
||||
framebuffer->z_buffer = 0;
|
||||
framebuffer->stencil_buffer = 0;
|
||||
framebuffer->colorFormat = Draw::DataFormat::UNDEFINED;
|
||||
}
|
||||
delete framebuffer;
|
||||
}
|
||||
|
@ -51,10 +51,9 @@ public:
|
||||
|
||||
class GLRFramebuffer {
|
||||
public:
|
||||
GLRFramebuffer(const Draw::DeviceCaps &caps, int _width, int _height, bool z_stencil)
|
||||
GLRFramebuffer(const Draw::DeviceCaps &caps, Draw::DataFormat _colorFormat, int _width, int _height, bool z_stencil)
|
||||
: color_texture(caps, _width, _height, 1, 1), z_stencil_texture(caps, _width, _height, 1, 1),
|
||||
width(_width), height(_height), z_stencil_(z_stencil) {
|
||||
}
|
||||
colorFormat(_colorFormat), width(_width), height(_height), z_stencil_(z_stencil) {}
|
||||
|
||||
~GLRFramebuffer();
|
||||
|
||||
@ -65,6 +64,7 @@ public:
|
||||
GLRTexture z_stencil_texture;
|
||||
GLuint z_buffer = 0;
|
||||
GLuint stencil_buffer = 0;
|
||||
Draw::DataFormat colorFormat;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
@ -464,9 +464,9 @@ public:
|
||||
return step.create_shader.shader;
|
||||
}
|
||||
|
||||
GLRFramebuffer *CreateFramebuffer(int width, int height, bool z_stencil) {
|
||||
GLRFramebuffer *CreateFramebuffer(Draw::DataFormat colorFormat, int width, int height, bool z_stencil) {
|
||||
GLRInitStep step{ GLRInitStepType::CREATE_FRAMEBUFFER };
|
||||
step.create_framebuffer.framebuffer = new GLRFramebuffer(caps_, width, height, z_stencil);
|
||||
step.create_framebuffer.framebuffer = new GLRFramebuffer(caps_, colorFormat, width, height, z_stencil);
|
||||
initSteps_.push_back(step);
|
||||
return step.create_framebuffer.framebuffer;
|
||||
}
|
||||
|
@ -1437,7 +1437,7 @@ Framebuffer *OpenGLContext::CreateFramebuffer(const FramebufferDesc &desc) {
|
||||
// TODO: Support multiview later. (It's our only use case for multi layers).
|
||||
_dbg_assert_(desc.numLayers == 1);
|
||||
|
||||
GLRFramebuffer *framebuffer = renderManager_.CreateFramebuffer(desc.width, desc.height, desc.z_stencil);
|
||||
GLRFramebuffer *framebuffer = renderManager_.CreateFramebuffer(desc.colorFormat, desc.width, desc.height, desc.z_stencil);
|
||||
OpenGLFramebuffer *fbo = new OpenGLFramebuffer(&renderManager_, framebuffer);
|
||||
return fbo;
|
||||
}
|
||||
|
@ -35,12 +35,12 @@ void VKRImage::Delete(VulkanContext *vulkan) {
|
||||
}
|
||||
}
|
||||
|
||||
VKRFramebuffer::VKRFramebuffer(VulkanContext *vk, VkCommandBuffer initCmd, VKRRenderPass *compatibleRenderPass, int _width, int _height, int _numLayers, int _multiSampleLevel, bool createDepthStencilBuffer, const char *tag)
|
||||
VKRFramebuffer::VKRFramebuffer(VulkanContext *vk, VkCommandBuffer initCmd, VKRRenderPass *compatibleRenderPass, VkFormat colorFormat, int _width, int _height, int _numLayers, int _multiSampleLevel, bool createDepthStencilBuffer, const char *tag)
|
||||
: vulkan_(vk), tag_(tag), width(_width), height(_height), numLayers(_numLayers) {
|
||||
|
||||
_dbg_assert_(tag);
|
||||
|
||||
CreateImage(vulkan_, initCmd, color, width, height, numLayers, VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true, tag);
|
||||
CreateImage(vulkan_, initCmd, color, width, height, numLayers, VK_SAMPLE_COUNT_1_BIT, colorFormat, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true, tag);
|
||||
if (createDepthStencilBuffer) {
|
||||
CreateImage(vulkan_, initCmd, depth, width, height, numLayers, VK_SAMPLE_COUNT_1_BIT, vulkan_->GetDeviceInfo().preferredDepthStencilFormat, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false, tag);
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ struct VKRImage {
|
||||
|
||||
class VKRFramebuffer {
|
||||
public:
|
||||
VKRFramebuffer(VulkanContext *vk, VkCommandBuffer initCmd, VKRRenderPass *compatibleRenderPass, int _width, int _height, int _numLayers, int _multiSampleLevel, bool createDepthStencilBuffer, const char *tag);
|
||||
VKRFramebuffer(VulkanContext *vk, VkCommandBuffer initCmd, VKRRenderPass *compatibleRenderPass, VkFormat colorFormat, int _width, int _height, int _numLayers, int _multiSampleLevel, bool createDepthStencilBuffer, const char *tag);
|
||||
~VKRFramebuffer();
|
||||
|
||||
VkFramebuffer Get(VKRRenderPass *compatibleRenderPass, RenderPassType rpType);
|
||||
|
@ -415,7 +415,8 @@ public:
|
||||
void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override;
|
||||
bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override;
|
||||
bool CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, const char *tag) override;
|
||||
DataFormat PreferredFramebufferReadbackFormat(Framebuffer *src) override;
|
||||
DataFormat PreferredColorReadbackFormat(Framebuffer *src) override;
|
||||
DataFormat PreferredDepthReadbackFormat(Framebuffer *src) override;
|
||||
|
||||
// These functions should be self explanatory.
|
||||
void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override;
|
||||
@ -1602,8 +1603,12 @@ Framebuffer *VKContext::CreateFramebuffer(const FramebufferDesc &desc) {
|
||||
_assert_(desc.width > 0);
|
||||
_assert_(desc.height > 0);
|
||||
|
||||
_assert_(desc.colorFormat == DataFormat::R8G8B8A8_UNORM || desc.colorFormat == DataFormat::R16_UNORM);
|
||||
|
||||
VkFormat colorFormat = DataFormatToVulkan(desc.colorFormat);
|
||||
|
||||
VkCommandBuffer cmd = renderManager_.GetInitCmd();
|
||||
VKRFramebuffer *vkrfb = new VKRFramebuffer(vulkan_, cmd, renderManager_.GetQueueRunner()->GetCompatibleRenderPass(), desc.width, desc.height, desc.numLayers, desc.multiSampleLevel, desc.z_stencil, desc.tag);
|
||||
VKRFramebuffer *vkrfb = new VKRFramebuffer(vulkan_, cmd, renderManager_.GetQueueRunner()->GetCompatibleRenderPass(), colorFormat, desc.width, desc.height, desc.numLayers, desc.multiSampleLevel, desc.z_stencil, desc.tag);
|
||||
return new VKFramebuffer(vkrfb, desc.multiSampleLevel);
|
||||
}
|
||||
|
||||
@ -1643,15 +1648,19 @@ bool VKContext::CopyFramebufferToMemorySync(Framebuffer *srcfb, int channelBits,
|
||||
return renderManager_.CopyFramebufferToMemorySync(src ? src->GetFB() : nullptr, aspectMask, x, y, w, h, format, (uint8_t *)pixels, pixelStride, tag);
|
||||
}
|
||||
|
||||
DataFormat VKContext::PreferredFramebufferReadbackFormat(Framebuffer *src) {
|
||||
DataFormat VKContext::PreferredColorReadbackFormat(Framebuffer *src) {
|
||||
if (src) {
|
||||
return DrawContext::PreferredFramebufferReadbackFormat(src);
|
||||
return DrawContext::PreferredColorReadbackFormat(src);
|
||||
}
|
||||
|
||||
if (vulkan_->GetSwapchainFormat() == VK_FORMAT_B8G8R8A8_UNORM) {
|
||||
return Draw::DataFormat::B8G8R8A8_UNORM;
|
||||
}
|
||||
return DrawContext::PreferredFramebufferReadbackFormat(src);
|
||||
return DrawContext::PreferredColorReadbackFormat(src);
|
||||
}
|
||||
|
||||
DataFormat VKContext::PreferredDepthReadbackFormat(Framebuffer *src) {
|
||||
return Draw::DataFormat::R16_UNORM;
|
||||
}
|
||||
|
||||
void VKContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) {
|
||||
|
@ -295,6 +295,7 @@ enum class Event {
|
||||
constexpr uint32_t MAX_TEXTURE_SLOTS = 3;
|
||||
|
||||
struct FramebufferDesc {
|
||||
DataFormat colorFormat;
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
@ -696,9 +697,13 @@ public:
|
||||
virtual bool CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, const char *tag) {
|
||||
return false;
|
||||
}
|
||||
virtual DataFormat PreferredFramebufferReadbackFormat(Framebuffer *src) {
|
||||
virtual DataFormat PreferredColorReadbackFormat(Framebuffer *src) {
|
||||
return DataFormat::R8G8B8A8_UNORM;
|
||||
}
|
||||
virtual DataFormat PreferredDepthReadbackFormat(Framebuffer *src) {
|
||||
// We use a shader to read depth and write color, while scaling.
|
||||
return DataFormat::R16_UNORM;
|
||||
}
|
||||
|
||||
// These functions should be self explanatory.
|
||||
// Binding a zero render target means binding the backbuffer.
|
||||
|
@ -1689,7 +1689,7 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w,
|
||||
char tag[128];
|
||||
size_t len = FormatFramebufferName(vfb, tag, sizeof(tag));
|
||||
|
||||
vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), msaaLevel_, true, tag });
|
||||
vfb->fbo = draw_->CreateFramebuffer({ colorFormat_, vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), msaaLevel_, true, tag });
|
||||
if (Memory::IsVRAMAddress(vfb->fb_address) && vfb->fb_stride != 0) {
|
||||
NotifyMemInfo(MemBlockFlags::ALLOC, vfb->fb_address, ColorBufferByteSize(vfb), tag, len);
|
||||
}
|
||||
@ -2060,7 +2060,7 @@ VirtualFramebuffer *FramebufferManagerCommon::CreateRAMFramebuffer(uint32_t fbAd
|
||||
char name[64];
|
||||
snprintf(name, sizeof(name), "%08x_color_RAM", vfb->fb_address);
|
||||
textureCache_->NotifyFramebuffer(vfb, NOTIFY_FB_CREATED);
|
||||
vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), 0, true, name });
|
||||
vfb->fbo = draw_->CreateFramebuffer({ colorFormat_, vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), 0, true, name });
|
||||
vfbs_.push_back(vfb);
|
||||
|
||||
u32 byteSize = ColorBufferByteSize(vfb);
|
||||
@ -2112,8 +2112,7 @@ VirtualFramebuffer *FramebufferManagerCommon::FindDownloadTempBuffer(VirtualFram
|
||||
char name[64];
|
||||
snprintf(name, sizeof(name), "download_temp");
|
||||
// TODO: We don't have a way to create a depth-only framebuffer yet.
|
||||
// Also, at least on Vulkan we always create both depth and color, need to rework how we handle renderpasses.
|
||||
nvfb->fbo = draw_->CreateFramebuffer({ nvfb->bufferWidth, nvfb->bufferHeight, 1, 1, 0, channel == RASTER_DEPTH ? true : false, name });
|
||||
nvfb->fbo = draw_->CreateFramebuffer({ colorFormat_, nvfb->bufferWidth, nvfb->bufferHeight, 1, 1, 0, channel == RASTER_DEPTH ? true : false, name });
|
||||
if (!nvfb->fbo) {
|
||||
ERROR_LOG(FRAMEBUF, "Error creating FBO! %d x %d", nvfb->renderWidth, nvfb->renderHeight);
|
||||
delete nvfb;
|
||||
@ -2496,7 +2495,7 @@ static const char *TempFBOReasonToString(TempFBO reason) {
|
||||
}
|
||||
|
||||
Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(TempFBO reason, u16 w, u16 h) {
|
||||
u64 key = ((u64)reason << 48) | ((u32)w << 16) | h;
|
||||
u64 key = ((u64)reason << 48) | ((u64)w << 16) | h;
|
||||
auto it = tempFBOs_.find(key);
|
||||
if (it != tempFBOs_.end()) {
|
||||
it->second.last_frame_used = gpuStats.numFlips;
|
||||
@ -2507,7 +2506,7 @@ Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(TempFBO reason, u16 w, u
|
||||
char name[128];
|
||||
snprintf(name, sizeof(name), "tempfbo_%s_%dx%d", TempFBOReasonToString(reason), w / renderScaleFactor_, h / renderScaleFactor_);
|
||||
|
||||
Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ w, h, 1, GetFramebufferLayers(), 0, z_stencil, name });
|
||||
Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ colorFormat_, w, h, 1, GetFramebufferLayers(), 0, z_stencil, name });
|
||||
if (!fbo) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -2699,7 +2698,7 @@ bool FramebufferManagerCommon::GetStencilbuffer(u32 fb_address, int fb_stride, G
|
||||
bool FramebufferManagerCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
|
||||
int w, h;
|
||||
draw_->GetFramebufferDimensions(nullptr, &w, &h);
|
||||
Draw::DataFormat fmt = draw_->PreferredFramebufferReadbackFormat(nullptr);
|
||||
Draw::DataFormat fmt = draw_->PreferredColorReadbackFormat(nullptr);
|
||||
// Ignore preferred formats other than BGRA.
|
||||
if (fmt != Draw::DataFormat::B8G8R8A8_UNORM)
|
||||
fmt = Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
@ -3202,7 +3201,7 @@ VirtualFramebuffer *FramebufferManagerCommon::ResolveFramebufferColorToFormat(Vi
|
||||
|
||||
char tag[128];
|
||||
FormatFramebufferName(vfb, tag, sizeof(tag));
|
||||
vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), 0, true, tag });
|
||||
vfb->fbo = draw_->CreateFramebuffer({ colorFormat_, vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), 0, true, tag });
|
||||
vfbs_.push_back(vfb);
|
||||
}
|
||||
|
||||
|
@ -605,4 +605,6 @@ protected:
|
||||
|
||||
Draw2D draw2D_;
|
||||
// The fragment shaders are "owned" by the pipelines since they're 1:1.
|
||||
|
||||
const Draw::DataFormat colorFormat_ = Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
};
|
||||
|
@ -278,7 +278,7 @@ bool PresentationCommon::UpdatePostShader() {
|
||||
previousIndex_ = 0;
|
||||
|
||||
for (int i = 0; i < FRAMES; ++i) {
|
||||
previousFramebuffers_[i] = draw_->CreateFramebuffer({ w, h, 1, 1, 0, false, "inter_presentation" });
|
||||
previousFramebuffers_[i] = draw_->CreateFramebuffer({ Draw::DataFormat::R8G8B8A8_UNORM, w, h, 1, 1, 0, false, "inter_presentation" });
|
||||
if (!previousFramebuffers_[i]) {
|
||||
DestroyPostShader();
|
||||
return false;
|
||||
@ -394,7 +394,7 @@ bool PresentationCommon::AllocateFramebuffer(int w, int h) {
|
||||
}
|
||||
|
||||
// No depth/stencil for post processing
|
||||
Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ w, h, 1, 1, 0, false, "presentation" });
|
||||
Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ Draw::DataFormat::R8G8B8A8_UNORM, w, h, 1, 1, 0, false, "presentation" });
|
||||
if (!fbo) {
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user