mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-20 17:59:08 +02:00
Debugger: Fix texture preview in GLES.
Also, fix issues with the first view of a texture in Vulkan / D3D11.
This commit is contained in:
1 parent
bdf7fdc7a3
commit
db0989a9d0
7 files changed
+81
-19
No files matched your search
@@ -775,16 +775,18 @@ bool TextureCacheD3D11::DecodeTexture(u8 *output, const GPUgstate &state) {
|
||||
}
|
||||
|
||||
bool TextureCacheD3D11::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) {
|
||||
ApplyTexture();
|
||||
SetTexture(false);
|
||||
if (!nextTexture_)
|
||||
return false;
|
||||
|
||||
// Apply texture may need to rebuild the texture if we're about to render, or bind a framebuffer.
|
||||
TexCacheEntry *entry = nextTexture_;
|
||||
ApplyTexture();
|
||||
|
||||
// TODO: Centralize.
|
||||
if (nextTexture_->framebuffer) {
|
||||
VirtualFramebuffer *vfb = nextTexture_->framebuffer;
|
||||
bool flipY = GetGPUBackend() == GPUBackend::OPENGL && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
|
||||
buffer.Allocate(vfb->bufferWidth, vfb->bufferHeight, GPU_DBG_FORMAT_8888, flipY);
|
||||
if (entry->framebuffer) {
|
||||
VirtualFramebuffer *vfb = entry->framebuffer;
|
||||
buffer.Allocate(vfb->bufferWidth, vfb->bufferHeight, GPU_DBG_FORMAT_8888, false);
|
||||
bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, 0, 0, vfb->bufferWidth, vfb->bufferHeight, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), vfb->bufferWidth);
|
||||
// Vulkan requires us to re-apply all dynamic state for each command buffer, and the above will cause us to start a new cmdbuf.
|
||||
// So let's dirty the things that are involved in Vulkan dynamic state. Readbacks are not frequent so this won't hurt other backends.
|
||||
@@ -794,7 +796,7 @@ bool TextureCacheD3D11::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level
|
||||
return retval;
|
||||
}
|
||||
|
||||
ID3D11Texture2D *texture = (ID3D11Texture2D *)nextTexture_->texturePtr;
|
||||
ID3D11Texture2D *texture = (ID3D11Texture2D *)entry->texturePtr;
|
||||
if (!texture)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -907,19 +907,40 @@ bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level)
|
||||
}
|
||||
|
||||
SetTexture(true);
|
||||
if (!nextTexture_)
|
||||
return false;
|
||||
|
||||
// Apply texture may need to rebuild the texture if we're about to render, or bind a framebuffer.
|
||||
TexCacheEntry *entry = nextTexture_;
|
||||
ApplyTexture();
|
||||
|
||||
// TODO: Centralize?
|
||||
if (entry->framebuffer) {
|
||||
VirtualFramebuffer *vfb = entry->framebuffer;
|
||||
buffer.Allocate(vfb->bufferWidth, vfb->bufferHeight, GPU_DBG_FORMAT_8888, false);
|
||||
bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, 0, 0, vfb->bufferWidth, vfb->bufferHeight, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), vfb->bufferWidth);
|
||||
// Vulkan requires us to re-apply all dynamic state for each command buffer, and the above will cause us to start a new cmdbuf.
|
||||
// So let's dirty the things that are involved in Vulkan dynamic state. Readbacks are not frequent so this won't hurt other backends.
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE);
|
||||
// We may have blitted to a temp FBO.
|
||||
framebufferManager_->RebindFramebuffer();
|
||||
return retval;
|
||||
}
|
||||
|
||||
GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
|
||||
// Not a framebuffer, so let's assume these are right.
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
|
||||
|
||||
if (level != 0) {
|
||||
gstate = saved;
|
||||
}
|
||||
|
||||
buffer.Allocate(w, h, GE_FORMAT_8888, false);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.GetData());
|
||||
renderManager->CopyImageToMemorySync(entry->textureName, level, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, (uint8_t *)buffer.GetData(), w);
|
||||
gstate_c.Dirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
|
||||
framebufferManager_->RebindFramebuffer();
|
||||
|
||||
return true;
|
||||
#else
|
||||
|
||||
@@ -784,16 +784,18 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePt
|
||||
}
|
||||
|
||||
bool TextureCacheVulkan::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) {
|
||||
ApplyTexture();
|
||||
SetTexture(false);
|
||||
if (!nextTexture_)
|
||||
return false;
|
||||
|
||||
// Apply texture may need to rebuild the texture if we're about to render, or bind a framebuffer.
|
||||
TexCacheEntry *entry = nextTexture_;
|
||||
ApplyTexture();
|
||||
|
||||
// TODO: Centralize?
|
||||
if (nextTexture_->framebuffer) {
|
||||
VirtualFramebuffer *vfb = nextTexture_->framebuffer;
|
||||
bool flipY = GetGPUBackend() == GPUBackend::OPENGL && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
|
||||
buffer.Allocate(vfb->bufferWidth, vfb->bufferHeight, GPU_DBG_FORMAT_8888, flipY);
|
||||
if (entry->framebuffer) {
|
||||
VirtualFramebuffer *vfb = entry->framebuffer;
|
||||
buffer.Allocate(vfb->bufferWidth, vfb->bufferHeight, GPU_DBG_FORMAT_8888, false);
|
||||
bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, 0, 0, vfb->bufferWidth, vfb->bufferHeight, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), vfb->bufferWidth);
|
||||
// Vulkan requires us to re-apply all dynamic state for each command buffer, and the above will cause us to start a new cmdbuf.
|
||||
// So let's dirty the things that are involved in Vulkan dynamic state. Readbacks are not frequent so this won't hurt other backends.
|
||||
@@ -803,9 +805,9 @@ bool TextureCacheVulkan::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int leve
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (!nextTexture_->vkTex || !nextTexture_->vkTex->texture_)
|
||||
if (!entry->vkTex || !entry->vkTex->texture_)
|
||||
return false;
|
||||
VulkanTexture *texture = nextTexture_->vkTex->texture_;
|
||||
VulkanTexture *texture = entry->vkTex->texture_;
|
||||
VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
|
||||
GPUDebugBufferFormat bufferFormat;
|
||||
|
||||
@@ -947,7 +947,28 @@ void GLQueueRunner::PerformReadback(const GLRStep &pass) {
|
||||
}
|
||||
|
||||
void GLQueueRunner::PerformReadbackImage(const GLRStep &pass) {
|
||||
GLRTexture *tex = pass.readback_image.texture;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tex->texture);
|
||||
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
|
||||
int pixelStride = pass.readback_image.srcRect.w;
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
|
||||
GLRect2D rect = pass.readback.srcRect;
|
||||
|
||||
int size = 4 * rect.w * rect.h;
|
||||
if (size > readbackBufferSize_) {
|
||||
delete[] readbackBuffer_;
|
||||
readbackBuffer_ = new uint8_t[size];
|
||||
readbackBufferSize_ = size;
|
||||
}
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
glGetTexImage(GL_TEXTURE_2D, pass.readback_image.mipLevel, GL_RGBA, GL_UNSIGNED_BYTE, readbackBuffer_);
|
||||
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
}
|
||||
|
||||
void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) {
|
||||
|
||||
@@ -301,7 +301,7 @@ struct GLRStep {
|
||||
Draw::DataFormat dstFormat;
|
||||
} readback;
|
||||
struct {
|
||||
GLint texture;
|
||||
GLRTexture *texture;
|
||||
GLRect2D srcRect;
|
||||
int mipLevel;
|
||||
} readback_image;
|
||||
|
||||
@@ -276,6 +276,22 @@ bool GLRenderManager::CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspec
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLRenderManager::CopyImageToMemorySync(GLRTexture *texture, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride) {
|
||||
GLRStep *step = new GLRStep{ GLRStepType::READBACK_IMAGE };
|
||||
step->readback_image.texture = texture;
|
||||
step->readback_image.mipLevel = mipLevel;
|
||||
step->readback_image.srcRect = { x, y, w, h };
|
||||
steps_.push_back(step);
|
||||
|
||||
// Every step clears this state.
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE);
|
||||
|
||||
curRenderStep_ = nullptr;
|
||||
FlushSync();
|
||||
|
||||
queueRunner_.CopyReadbackBuffer(w, h, Draw::DataFormat::R8G8B8A8_UNORM, destFormat, pixelStride, pixels);
|
||||
}
|
||||
|
||||
void GLRenderManager::BeginFrame() {
|
||||
VLOG("BeginFrame");
|
||||
|
||||
|
||||
@@ -313,7 +313,7 @@ public:
|
||||
void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, GLRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil);
|
||||
void BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment);
|
||||
bool CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride);
|
||||
void CopyImageToMemorySync(GLuint texture, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride);
|
||||
void CopyImageToMemorySync(GLRTexture *texture, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride);
|
||||
|
||||
void CopyFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLOffset2D dstPos, int aspectMask);
|
||||
void BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLRect2D dstRect, int aspectMask, bool filter);
|
||||
|
||||
Reference in new issue
Block a user