mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 23:25:40 +12:00
renderer_gl: Implement semi proper clears
This commit is contained in:
parent
50bcf3b617
commit
c6c71bb9b2
4 changed files with 71 additions and 40 deletions
|
@ -333,18 +333,18 @@ namespace OpenGL {
|
||||||
void bind(FramebufferTypes target) const { bind(static_cast<GLenum>(target)); }
|
void bind(FramebufferTypes target) const { bind(static_cast<GLenum>(target)); }
|
||||||
void free() { glDeleteFramebuffers(1, &m_handle); }
|
void free() { glDeleteFramebuffers(1, &m_handle); }
|
||||||
|
|
||||||
void createWithTexture(Texture& tex, GLenum mode = GL_FRAMEBUFFER, GLenum textureType = GL_TEXTURE_2D) {
|
void createWithTexture(Texture& tex, GLenum mode = GL_FRAMEBUFFER, GLenum attachment = GL_COLOR_ATTACHMENT0, GLenum textureType = GL_TEXTURE_2D) {
|
||||||
m_textureType = textureType;
|
m_textureType = textureType;
|
||||||
create();
|
create();
|
||||||
bind(mode);
|
bind(mode);
|
||||||
glFramebufferTexture2D(mode, GL_COLOR_ATTACHMENT0, textureType, tex.handle(), 0);
|
glFramebufferTexture2D(mode, attachment, textureType, tex.handle(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createWithReadTexture(Texture& tex, GLenum textureType = GL_TEXTURE_2D) {
|
void createWithReadTexture(Texture& tex, GLenum attachment = GL_COLOR_ATTACHMENT0, GLenum textureType = GL_TEXTURE_2D) {
|
||||||
createWithTexture(tex, GL_READ_FRAMEBUFFER, textureType);
|
createWithTexture(tex, GL_READ_FRAMEBUFFER, attachment, textureType);
|
||||||
}
|
}
|
||||||
void createWithDrawTexture(Texture& tex, GLenum textureType = GL_TEXTURE_2D) {
|
void createWithDrawTexture(Texture& tex, GLenum attachment = GL_COLOR_ATTACHMENT0, GLenum textureType = GL_TEXTURE_2D) {
|
||||||
createWithTexture(tex, GL_DRAW_FRAMEBUFFER, textureType);
|
createWithTexture(tex, GL_DRAW_FRAMEBUFFER, attachment, textureType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createWithTextureMSAA(Texture& tex, GLenum mode = GL_FRAMEBUFFER) {
|
void createWithTextureMSAA(Texture& tex, GLenum mode = GL_FRAMEBUFFER) {
|
||||||
|
|
|
@ -86,6 +86,7 @@ struct DepthBuffer {
|
||||||
Interval<u32> range;
|
Interval<u32> range;
|
||||||
// OpenGL texture used for storing depth/stencil
|
// OpenGL texture used for storing depth/stencil
|
||||||
OpenGL::Texture texture;
|
OpenGL::Texture texture;
|
||||||
|
OpenGL::Framebuffer fbo;
|
||||||
|
|
||||||
DepthBuffer() : valid(false) {}
|
DepthBuffer() : valid(false) {}
|
||||||
|
|
||||||
|
@ -127,6 +128,11 @@ struct DepthBuffer {
|
||||||
texture.setMagFilter(OpenGL::Nearest);
|
texture.setMagFilter(OpenGL::Nearest);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, prevTexture);
|
glBindTexture(GL_TEXTURE_2D, prevTexture);
|
||||||
|
|
||||||
|
fbo.createWithDrawTexture(texture, fmt == GL_DEPTH_STENCIL ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT);
|
||||||
|
|
||||||
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
Helpers::panic("Incomplete framebuffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
void free() {
|
void free() {
|
||||||
|
@ -144,4 +150,4 @@ struct DepthBuffer {
|
||||||
size_t sizeInBytes() {
|
size_t sizeInBytes() {
|
||||||
return (size_t)size.x() * (size_t)size.y() * PICA::sizePerPixel(format);
|
return (size_t)size.x() * (size_t)size.y() * PICA::sizePerPixel(format);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -472,14 +472,8 @@ void RendererGL::display() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) {
|
void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) {
|
||||||
return;
|
|
||||||
log("GPU: Clear buffer\nStart: %08X End: %08X\nValue: %08X Control: %08X\n", startAddress, endAddress, value, control);
|
log("GPU: Clear buffer\nStart: %08X End: %08X\nValue: %08X Control: %08X\n", startAddress, endAddress, value, control);
|
||||||
|
|
||||||
const float r = float(getBits<24, 8>(value)) / 255.0f;
|
|
||||||
const float g = float(getBits<16, 8>(value)) / 255.0f;
|
|
||||||
const float b = float(getBits<8, 8>(value)) / 255.0f;
|
|
||||||
const float a = float(value & 0xff) / 255.0f;
|
|
||||||
|
|
||||||
if (startAddress == topScreenBuffer) {
|
if (startAddress == topScreenBuffer) {
|
||||||
log("GPU: Cleared top screen\n");
|
log("GPU: Cleared top screen\n");
|
||||||
} else if (startAddress == bottomScreenBuffer) {
|
} else if (startAddress == bottomScreenBuffer) {
|
||||||
|
@ -489,8 +483,39 @@ void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 co
|
||||||
log("GPU: Clearing some unknown buffer\n");
|
log("GPU: Clearing some unknown buffer\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGL::setClearColor(r, g, b, a);
|
const auto color = colourBufferCache.findFromAddress(startAddress);
|
||||||
OpenGL::clearColor();
|
if (color) {
|
||||||
|
const float r = getBits<24, 8>(value) / 255.0f;
|
||||||
|
const float g = getBits<16, 8>(value) / 255.0f;
|
||||||
|
const float b = getBits<8, 8>(value) / 255.0f;
|
||||||
|
const float a = (value & 0xff) / 255.0f;
|
||||||
|
color->get().fbo.bind(OpenGL::DrawFramebuffer);
|
||||||
|
gl.setColourMask(true, true, true, true);
|
||||||
|
OpenGL::setClearColor(r, g, b, a);
|
||||||
|
OpenGL::clearColor();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto depth = depthBufferCache.findFromAddress(startAddress);
|
||||||
|
if (depth) {
|
||||||
|
float depthVal;
|
||||||
|
const auto format = depth->get().format;
|
||||||
|
if (format == DepthFmt::Depth16) {
|
||||||
|
depthVal = (value & 0xffff) / 65535.0f;
|
||||||
|
} else {
|
||||||
|
depthVal = (value & 0xffffff) / 16777215.0f;
|
||||||
|
}
|
||||||
|
depth->get().fbo.bind(OpenGL::DrawFramebuffer);
|
||||||
|
OpenGL::setDepthMask(true);
|
||||||
|
OpenGL::setClearDepth(depthVal);
|
||||||
|
OpenGL::clearDepth();
|
||||||
|
if (format == DepthFmt::Depth24Stencil8) {
|
||||||
|
const u8 stencil = (value >> 24);
|
||||||
|
OpenGL::setStencilMask(0xFF);
|
||||||
|
OpenGL::setClearStencil(stencil);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Helpers::warn("GPU: No buffer found!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGL::Framebuffer RendererGL::getColourFBO() {
|
OpenGL::Framebuffer RendererGL::getColourFBO() {
|
||||||
|
|
|
@ -299,6 +299,28 @@ void GPUService::processCommandBuffer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 VaddrToPaddr(u32 addr) {
|
||||||
|
if (addr >= VirtualAddrs::VramStart && addr < (VirtualAddrs::VramStart + VirtualAddrs::VramSize)) [[likely]] {
|
||||||
|
return addr - VirtualAddrs::VramStart + PhysicalAddrs::VRAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (addr >= VirtualAddrs::LinearHeapStartOld && addr < VirtualAddrs::LinearHeapEndOld) {
|
||||||
|
return addr - VirtualAddrs::LinearHeapStartOld + PhysicalAddrs::FCRAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (addr >= VirtualAddrs::LinearHeapStartNew && addr < VirtualAddrs::LinearHeapEndNew) {
|
||||||
|
return addr - VirtualAddrs::LinearHeapStartNew + PhysicalAddrs::FCRAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (addr == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Helpers::warn("[GSP::GPU VaddrToPaddr] Unknown virtual address %08X", addr);
|
||||||
|
// Obviously garbage address
|
||||||
|
return 0xF3310932;
|
||||||
|
}
|
||||||
|
|
||||||
// Fill 2 GPU framebuffers, buf0 and buf1, using a specific word value
|
// Fill 2 GPU framebuffers, buf0 and buf1, using a specific word value
|
||||||
void GPUService::memoryFill(u32* cmd) {
|
void GPUService::memoryFill(u32* cmd) {
|
||||||
u32 control = cmd[7];
|
u32 control = cmd[7];
|
||||||
|
@ -316,38 +338,16 @@ void GPUService::memoryFill(u32* cmd) {
|
||||||
u32 control1 = control >> 16;
|
u32 control1 = control >> 16;
|
||||||
|
|
||||||
if (start0 != 0) {
|
if (start0 != 0) {
|
||||||
gpu.clearBuffer(start0, end0, value0, control0);
|
gpu.clearBuffer(VaddrToPaddr(start0), VaddrToPaddr(end0), value0, control0);
|
||||||
requestInterrupt(GPUInterrupt::PSC0);
|
requestInterrupt(GPUInterrupt::PSC0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start1 != 0) {
|
if (start1 != 0) {
|
||||||
gpu.clearBuffer(start1, end1, value1, control1);
|
gpu.clearBuffer(VaddrToPaddr(start1), VaddrToPaddr(end1), value1, control1);
|
||||||
requestInterrupt(GPUInterrupt::PSC1);
|
requestInterrupt(GPUInterrupt::PSC1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 VaddrToPaddr(u32 addr) {
|
|
||||||
if (addr >= VirtualAddrs::VramStart && addr < (VirtualAddrs::VramStart + VirtualAddrs::VramSize)) [[likely]] {
|
|
||||||
return addr - VirtualAddrs::VramStart + PhysicalAddrs::VRAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (addr >= VirtualAddrs::LinearHeapStartOld && addr < VirtualAddrs::LinearHeapEndOld) {
|
|
||||||
return addr - VirtualAddrs::LinearHeapStartOld + PhysicalAddrs::FCRAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (addr >= VirtualAddrs::LinearHeapStartNew && addr < VirtualAddrs::LinearHeapEndNew) {
|
|
||||||
return addr - VirtualAddrs::LinearHeapStartNew + PhysicalAddrs::FCRAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (addr == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Helpers::warn("[GSP::GPU VaddrToPaddr] Unknown virtual address %08X", addr);
|
|
||||||
// Obviously garbage address
|
|
||||||
return 0xF3310932;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPUService::triggerDisplayTransfer(u32* cmd) {
|
void GPUService::triggerDisplayTransfer(u32* cmd) {
|
||||||
const u32 inputAddr = VaddrToPaddr(cmd[1]);
|
const u32 inputAddr = VaddrToPaddr(cmd[1]);
|
||||||
const u32 outputAddr = VaddrToPaddr(cmd[2]);
|
const u32 outputAddr = VaddrToPaddr(cmd[2]);
|
||||||
|
@ -394,4 +394,4 @@ void GPUService::triggerTextureCopy(u32* cmd) {
|
||||||
// This uses the transfer engine and thus needs to fire a PPF interrupt.
|
// This uses the transfer engine and thus needs to fire a PPF interrupt.
|
||||||
// NSMB2 relies on this
|
// NSMB2 relies on this
|
||||||
requestInterrupt(GPUInterrupt::PPF);
|
requestInterrupt(GPUInterrupt::PPF);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue