mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 18:49:51 +01:00
Merge pull request #8454 from unknownbrackets/gpu-depth-round
Add pixel depth rounding to d3d9, gles2 and support forcing via config
This commit is contained in:
commit
cd35684a46
19 files changed
+218
-27
No files matched your search
@@ -442,6 +442,7 @@ static ConfigSetting graphicsSettings[] = {
|
||||
ReportedConfigSetting("BufferFiltering", &g_Config.iBufFilter, 1, true, true),
|
||||
ReportedConfigSetting("InternalResolution", &g_Config.iInternalResolution, &DefaultInternalResolution, true, true),
|
||||
ReportedConfigSetting("AndroidHwScale", &g_Config.iAndroidHwScale, &DefaultAndroidHwScale),
|
||||
ReportedConfigSetting("HighQualityDepth", &g_Config.bHighQualityDepth, true, true, true),
|
||||
ReportedConfigSetting("FrameSkip", &g_Config.iFrameSkip, 0, true, true),
|
||||
ReportedConfigSetting("AutoFrameSkip", &g_Config.bAutoFrameSkip, false, true, true),
|
||||
ReportedConfigSetting("FrameRate", &g_Config.iFpsLimit, 0, true, true),
|
||||
|
||||
@@ -173,6 +173,7 @@ public:
|
||||
bool bFullScreen;
|
||||
int iInternalResolution; // 0 = Auto (native), 1 = 1x (480x272), 2 = 2x, 3 = 3x, 4 = 4x and so on.
|
||||
int iAnisotropyLevel; // 0 - 5, powers of 2: 0 = 1x = no aniso
|
||||
int bHighQualityDepth;
|
||||
bool bTrueColor;
|
||||
bool bMipMap;
|
||||
int iTexScalingLevel; // 1 = off, 2 = 2x, ..., 5 = 5x
|
||||
|
||||
@@ -310,6 +310,8 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
|
||||
vfb->fb_stride = params.fb_stride;
|
||||
vfb->format = params.fmt;
|
||||
}
|
||||
// Keep track, but this isn't really used.
|
||||
vfb->z_stride = params.z_stride;
|
||||
// Heuristic: In throughmode, a higher height could be used. Let's avoid shrinking the buffer.
|
||||
if (params.isModeThrough && (int)vfb->width < params.fb_stride) {
|
||||
vfb->width = std::max((int)vfb->width, drawing_width);
|
||||
|
||||
@@ -57,6 +57,8 @@ u32 GPUDebugBuffer::PixelSize(GPUDebugBufferFormat fmt) const {
|
||||
case GPU_DBG_FORMAT_FLOAT:
|
||||
case GPU_DBG_FORMAT_24BIT_8X:
|
||||
case GPU_DBG_FORMAT_24X_8BIT:
|
||||
case GPU_DBG_FORMAT_FLOAT_DIV_256:
|
||||
case GPU_DBG_FORMAT_24BIT_8X_DIV_256:
|
||||
return 4;
|
||||
|
||||
case GPU_DBG_FORMAT_888_RGB:
|
||||
|
||||
@@ -59,6 +59,9 @@ enum GPUDebugBufferFormat {
|
||||
GPU_DBG_FORMAT_24BIT_8X = 0x13,
|
||||
GPU_DBG_FORMAT_24X_8BIT = 0x14,
|
||||
|
||||
GPU_DBG_FORMAT_FLOAT_DIV_256 = 0x18,
|
||||
GPU_DBG_FORMAT_24BIT_8X_DIV_256 = 0x1B,
|
||||
|
||||
// This is used for screenshots, mainly.
|
||||
GPU_DBG_FORMAT_888_RGB = 0x20,
|
||||
};
|
||||
|
||||
@@ -498,10 +498,19 @@ LogicOpReplaceType ReplaceLogicOpType() {
|
||||
return LOGICOPTYPE_NORMAL;
|
||||
}
|
||||
|
||||
static const float depthSliceFactor = 4.0f;
|
||||
static const float DEPTH_SLICE_FACTOR_HIGH = 4.0f;
|
||||
static const float DEPTH_SLICE_FACTOR_16BIT = 256.0f;
|
||||
|
||||
float DepthSliceFactor() {
|
||||
if (gstate_c.Supports(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) {
|
||||
return DEPTH_SLICE_FACTOR_16BIT;
|
||||
}
|
||||
return DEPTH_SLICE_FACTOR_HIGH;
|
||||
}
|
||||
|
||||
// This is used for float values which might not be integers, but are in the integer scale of 65535.
|
||||
static float ToScaledDepthFromInteger(float z) {
|
||||
const float depthSliceFactor = DepthSliceFactor();
|
||||
const float offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor);
|
||||
return z * (1.0f / depthSliceFactor) * (1.0f / 65535.0f) + offset;
|
||||
}
|
||||
@@ -511,14 +520,11 @@ float ToScaledDepth(u16 z) {
|
||||
}
|
||||
|
||||
float FromScaledDepth(float z) {
|
||||
const float depthSliceFactor = DepthSliceFactor();
|
||||
const float offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor);
|
||||
return (z - offset) * depthSliceFactor * 65535.0f;
|
||||
}
|
||||
|
||||
float DepthSliceFactor() {
|
||||
return depthSliceFactor;
|
||||
}
|
||||
|
||||
void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) {
|
||||
bool throughmode = gstate.isModeThrough();
|
||||
out.dirtyProj = false;
|
||||
@@ -662,7 +668,7 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
|
||||
// Here, we should "clamp." But clamping per fragment would be slow.
|
||||
// So, instead, we just increase the available range and hope.
|
||||
// If depthSliceFactor is 4, it means (75% / 2) of the depth lies in each direction.
|
||||
float fullDepthRange = 65535.0f * (depthSliceFactor - 1.0f) * (1.0f / 2.0f);
|
||||
float fullDepthRange = 65535.0f * (DepthSliceFactor() - 1.0f) * (1.0f / 2.0f);
|
||||
if (minz == 0) {
|
||||
minz -= fullDepthRange;
|
||||
}
|
||||
|
||||
@@ -1055,6 +1055,55 @@ namespace DX9 {
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerDX9::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
|
||||
if (!vfb->fbo) {
|
||||
ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackDepthbuffer: vfb->fbo == 0");
|
||||
return;
|
||||
}
|
||||
|
||||
// We always read the depth buffer in 24_8 format.
|
||||
const u32 z_address = (0x04000000) | vfb->z_address;
|
||||
|
||||
DEBUG_LOG(SCEGE, "Reading depthbuffer to mem at %08x for vfb=%08x", z_address, vfb->fb_address);
|
||||
|
||||
LPDIRECT3DTEXTURE9 tex = fbo_get_depth_texture(vfb->fbo_dx9);
|
||||
if (tex) {
|
||||
D3DSURFACE_DESC desc;
|
||||
D3DLOCKED_RECT locked;
|
||||
tex->GetLevelDesc(0, &desc);
|
||||
RECT rect = {0, 0, (LONG)desc.Width, (LONG)desc.Height};
|
||||
HRESULT hr = tex->LockRect(0, &locked, &rect, D3DLOCK_READONLY);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
const int dstByteOffset = y * vfb->fb_stride * sizeof(s16);
|
||||
const u32 *packed = (const u32 *)locked.pBits;
|
||||
u16 *depth = (u16 *)Memory::GetPointer(z_address);
|
||||
|
||||
// TODO: Optimize.
|
||||
for (int yp = 0; yp < h; ++yp) {
|
||||
for (int xp = 0; xp < w; ++xp) {
|
||||
const int offset = (yp + y) & vfb->z_stride + x + xp;
|
||||
|
||||
float scaled = FromScaledDepth((packed[offset] & 0x00FFFFFF) * (1.0f / 16777215.0f));
|
||||
if (scaled <= 0.0f) {
|
||||
depth[offset] = 0;
|
||||
} else if (scaled >= 65535.0f) {
|
||||
depth[offset] = 65535;
|
||||
} else {
|
||||
depth[offset] = (int)scaled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tex->UnlockRect(0);
|
||||
} else {
|
||||
ERROR_LOG_REPORT(G3D, "Unable to lock rect from depth %08x: %d,%d %dx%d of %dx%d", vfb->fb_address, rect.left, rect.top, rect.right, rect.bottom, vfb->renderWidth, vfb->renderHeight);
|
||||
}
|
||||
} else {
|
||||
ERROR_LOG_REPORT(G3D, "Unable to download render target depth from %08x", vfb->fb_address);
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerDX9::EndFrame() {
|
||||
if (resized_) {
|
||||
DestroyAllFBOs();
|
||||
@@ -1320,6 +1369,9 @@ namespace DX9 {
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
GPUDebugBufferFormat fmt = GPU_DBG_FORMAT_24BIT_8X;
|
||||
if (gstate_c.Supports(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) {
|
||||
fmt = GPU_DBG_FORMAT_24BIT_8X_DIV_256;
|
||||
}
|
||||
int pixelSize = 4;
|
||||
|
||||
buffer.Allocate(locked.Pitch / pixelSize, desc.Height, fmt, false);
|
||||
|
||||
@@ -115,6 +115,7 @@ private:
|
||||
void SetNumExtraFBOs(int num);
|
||||
|
||||
void PackFramebufferDirectx9_(VirtualFramebuffer *vfb, int x, int y, int w, int h);
|
||||
void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h);
|
||||
static bool GetRenderTargetFramebuffer(LPDIRECT3DSURFACE9 renderTarget, LPDIRECT3DSURFACE9 offscreen, int w, int h, GPUDebugBuffer &buffer);
|
||||
|
||||
// Used by DrawPixels
|
||||
|
||||
@@ -478,7 +478,12 @@ void DIRECTX9_GPU::CheckGPUFeatures() {
|
||||
features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL;
|
||||
features |= GPU_PREFER_CPU_DOWNLOAD;
|
||||
|
||||
if (PSP_CoreParameter().compat.flags().VertexDepthRounding) {
|
||||
if (!g_Config.bHighQualityDepth) {
|
||||
features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT;
|
||||
} else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) {
|
||||
// Assume we always have a 24-bit depth buffer.
|
||||
features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT;
|
||||
} else if (PSP_CoreParameter().compat.flags().VertexDepthRounding) {
|
||||
features |= GPU_ROUND_DEPTH_TO_16BIT;
|
||||
}
|
||||
|
||||
|
||||
@@ -488,7 +488,8 @@ void ShaderManagerDX9::VSUpdateUniforms(int dirtyUniforms) {
|
||||
float halfActualZRange = vpZScale / gstate_c.vpDepthScale;
|
||||
float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange;
|
||||
float viewZScale = halfActualZRange * 2.0f;
|
||||
float viewZCenter = minz;
|
||||
// Account for the half pixel offset.
|
||||
float viewZCenter = minz + (DepthSliceFactor() / 256.0f) * 0.5f;
|
||||
float viewZInvScale;
|
||||
|
||||
if (viewZScale != 0.0) {
|
||||
|
||||
@@ -143,6 +143,18 @@ int fbo_check_framebuffer_status(FBO *fbo) {
|
||||
return (int)fbStatus;
|
||||
}
|
||||
|
||||
int fbo_standard_z_depth() {
|
||||
// This matches the fbo_create() logic.
|
||||
if (gl_extensions.IsGLES) {
|
||||
if (gl_extensions.OES_packed_depth_stencil) {
|
||||
return 24;
|
||||
}
|
||||
return gl_extensions.OES_depth24 ? 24 : 16;
|
||||
} else {
|
||||
return 24;
|
||||
}
|
||||
}
|
||||
|
||||
FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) {
|
||||
CheckGLExtensions();
|
||||
|
||||
@@ -216,6 +228,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F
|
||||
// 16/24-bit Z, separate 8-bit stencil
|
||||
glGenRenderbuffers(1, &fbo->z_buffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer);
|
||||
// Don't forget to make sure fbo_standard_z_depth() matches.
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, width, height);
|
||||
|
||||
// 8-bit stencil buffer
|
||||
|
||||
@@ -43,6 +43,8 @@ enum FBOColorDepth {
|
||||
// On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one.
|
||||
FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth = FBO_8888);
|
||||
|
||||
int fbo_standard_z_depth();
|
||||
|
||||
// Create an opaque FBO from a native GL FBO, optionally reusing an existing FBO structure.
|
||||
// Useful for overriding the backbuffer FBO that is generated outside of this wrapper.
|
||||
FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo = NULL);
|
||||
|
||||
+60
-14
@@ -1677,30 +1677,30 @@ void FramebufferManager::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, in
|
||||
}
|
||||
|
||||
// Pixel size always 4 here because we always request RGBA8888
|
||||
size_t bufSize = vfb->fb_stride * std::max(vfb->height, (u16)h) * 4;
|
||||
u32 bufSize = vfb->fb_stride * (h - y) * 4;
|
||||
u32 fb_address = (0x04000000) | vfb->fb_address;
|
||||
|
||||
GLubyte *packed = 0;
|
||||
|
||||
bool convert = vfb->format != GE_FORMAT_8888 || UseBGRA8888();
|
||||
const int dstBpp = vfb->format == GE_FORMAT_8888 ? 4 : 2;
|
||||
const int packWidth = x + w < vfb->width ? x + w : vfb->width;
|
||||
const int packWidth = std::min(vfb->fb_stride, std::min(x + w, (int)vfb->width));
|
||||
|
||||
if (!convert) {
|
||||
packed = (GLubyte *)Memory::GetPointer(fb_address);
|
||||
} else { // End result may be 16-bit but we are reading 32-bit, so there may not be enough space at fb_address
|
||||
u32 neededSize = (u32)bufSize * sizeof(GLubyte);
|
||||
if (!convBuf_ || convBufSize_ < neededSize) {
|
||||
int byteOffset = y * vfb->fb_stride * 4;
|
||||
packed = (GLubyte *)Memory::GetPointer(fb_address + byteOffset);
|
||||
} else {
|
||||
// End result may be 16-bit but we are reading 32-bit, so there may not be enough space at fb_address
|
||||
if (!convBuf_ || convBufSize_ < bufSize) {
|
||||
delete [] convBuf_;
|
||||
convBuf_ = new u8[neededSize];
|
||||
convBufSize_ = neededSize;
|
||||
convBuf_ = new u8[bufSize];
|
||||
convBufSize_ = bufSize;
|
||||
}
|
||||
packed = convBuf_;
|
||||
}
|
||||
|
||||
if (packed) {
|
||||
DEBUG_LOG(SCEGE, "Reading framebuffer to mem, bufSize = %u, packed = %p, fb_address = %08x",
|
||||
(u32)bufSize, packed, fb_address);
|
||||
DEBUG_LOG(SCEGE, "Reading framebuffer to mem, bufSize = %u, fb_address = %08x", bufSize, fb_address);
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
GLenum glfmt = GL_RGBA;
|
||||
@@ -1708,12 +1708,11 @@ void FramebufferManager::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, in
|
||||
glfmt = GL_BGRA_EXT;
|
||||
}
|
||||
|
||||
int byteOffset = y * vfb->fb_stride * 4;
|
||||
SafeGLReadPixels(0, y, h == 1 ? packWidth : vfb->fb_stride, h, glfmt, GL_UNSIGNED_BYTE, packed + byteOffset);
|
||||
SafeGLReadPixels(0, y, h == 1 ? packWidth : vfb->fb_stride, h, glfmt, GL_UNSIGNED_BYTE, packed);
|
||||
|
||||
if (convert) {
|
||||
int dstByteOffset = y * vfb->fb_stride * dstBpp;
|
||||
ConvertFromRGBA8888(Memory::GetPointer(fb_address + dstByteOffset), packed + byteOffset, vfb->fb_stride, vfb->fb_stride, packWidth, h, vfb->format);
|
||||
ConvertFromRGBA8888(Memory::GetPointer(fb_address + dstByteOffset), packed, vfb->fb_stride, vfb->fb_stride, packWidth, h, vfb->format);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1732,6 +1731,49 @@ void FramebufferManager::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, in
|
||||
fbo_unbind_read();
|
||||
}
|
||||
|
||||
void FramebufferManager::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
|
||||
if (vfb->fbo) {
|
||||
fbo_bind_for_read(vfb->fbo);
|
||||
} else {
|
||||
ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackDepthbuffer: vfb->fbo == 0");
|
||||
return;
|
||||
}
|
||||
|
||||
// Pixel size always 4 here because we always request float
|
||||
const u32 bufSize = vfb->z_stride * (h - y) * 4;
|
||||
const u32 z_address = (0x04000000) | vfb->z_address;
|
||||
const int packWidth = std::min(vfb->z_stride, std::min(x + w, (int)vfb->width));
|
||||
|
||||
if (!convBuf_ || convBufSize_ < bufSize) {
|
||||
delete [] convBuf_;
|
||||
convBuf_ = new u8[bufSize];
|
||||
convBufSize_ = bufSize;
|
||||
}
|
||||
|
||||
DEBUG_LOG(SCEGE, "Reading depthbuffer to mem at %08x for vfb=%08x", z_address, vfb->fb_address);
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
SafeGLReadPixels(0, y, h == 1 ? packWidth : vfb->z_stride, h, GL_DEPTH_COMPONENT, GL_FLOAT, convBuf_);
|
||||
|
||||
int dstByteOffset = y * vfb->fb_stride * sizeof(u16);
|
||||
u16 *depth = (u16 *)Memory::GetPointer(z_address + dstByteOffset);
|
||||
GLfloat *packed = (GLfloat *)convBuf_;
|
||||
|
||||
int totalPixels = h == 1 ? packWidth : vfb->z_stride * h;
|
||||
for (int i = 0; i < totalPixels; ++i) {
|
||||
float scaled = FromScaledDepth(packed[i]);
|
||||
if (scaled <= 0.0f) {
|
||||
depth[i] = 0;
|
||||
} else if (scaled >= 65535.0f) {
|
||||
depth[i] = 65535;
|
||||
} else {
|
||||
depth[i] = (int)scaled;
|
||||
}
|
||||
}
|
||||
|
||||
fbo_unbind_read();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void ShowScreenResolution();
|
||||
#endif
|
||||
@@ -1972,7 +2014,11 @@ bool FramebufferManager::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_add
|
||||
return true;
|
||||
}
|
||||
|
||||
buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_FLOAT, false);
|
||||
if (gstate_c.Supports(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) {
|
||||
buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_FLOAT_DIV_256, false);
|
||||
} else {
|
||||
buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_FLOAT, false);
|
||||
}
|
||||
if (vfb->fbo)
|
||||
fbo_bind_for_read(vfb->fbo);
|
||||
if (gl_extensions.GLES3 || !gl_extensions.IsGLES)
|
||||
|
||||
@@ -145,6 +145,7 @@ private:
|
||||
|
||||
void PackFramebufferAsync_(VirtualFramebuffer *vfb); // Not used under ES currently
|
||||
void PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h);
|
||||
void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h);
|
||||
|
||||
// Used by DrawPixels
|
||||
unsigned int drawPixelsTex_;
|
||||
|
||||
+17
-5
@@ -565,11 +565,23 @@ void GLES_GPU::CheckGPUFeatures() {
|
||||
if (gl_extensions.GLES3 || !gl_extensions.IsGLES)
|
||||
features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL;
|
||||
|
||||
// In the future, also disable this when we get a proper 16-bit depth buffer.
|
||||
if ((!gl_extensions.IsGLES || gl_extensions.GLES3) && PSP_CoreParameter().compat.flags().PixelDepthRounding) {
|
||||
features |= GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT;
|
||||
} else {
|
||||
if (PSP_CoreParameter().compat.flags().VertexDepthRounding) {
|
||||
// If we already have a 16-bit depth buffer, we don't need to round.
|
||||
if (fbo_standard_z_depth() > 16) {
|
||||
if (!g_Config.bHighQualityDepth) {
|
||||
features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT;
|
||||
} else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) {
|
||||
if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
|
||||
// Use fragment rounding on desktop and GLES3, most accurate.
|
||||
features |= GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT;
|
||||
} else if (fbo_standard_z_depth() == 24) {
|
||||
// Here we can simulate a 16 bit depth buffer by scaling.
|
||||
// Note that the depth buffer is fixed point, not floating, so dividing by 256 is pretty good.
|
||||
features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT;
|
||||
} else {
|
||||
// At least do vertex rounding if nothing else.
|
||||
features |= GPU_ROUND_DEPTH_TO_16BIT;
|
||||
}
|
||||
} else if (PSP_CoreParameter().compat.flags().VertexDepthRounding) {
|
||||
features |= GPU_ROUND_DEPTH_TO_16BIT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,6 +458,7 @@ enum {
|
||||
GPU_SUPPORTS_VAO = FLAG_BIT(18),
|
||||
GPU_SUPPORTS_ANY_COPY_IMAGE = FLAG_BIT(19),
|
||||
GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH = FLAG_BIT(20),
|
||||
GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT = FLAG_BIT(21),
|
||||
GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT = FLAG_BIT(22),
|
||||
GPU_ROUND_DEPTH_TO_16BIT = FLAG_BIT(23), // Can be disabled either per game or if we use a real 16-bit depth buffer
|
||||
GPU_SUPPORTS_TEXTURE_LOD_CONTROL = FLAG_BIT(24),
|
||||
|
||||
@@ -402,6 +402,15 @@ void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y,
|
||||
_snwprintf(desc, 256, L"%d,%d: %d / %f / %f", x, y, pix & 0x00FFFFFF, (pix & 0x00FFFFFF) * (1.0f / 16777215.0f), FromScaledDepth((pix & 0x00FFFFFF) * (1.0f / 16777215.0f)));
|
||||
break;
|
||||
|
||||
case GPU_DBG_FORMAT_24BIT_8X_DIV_256:
|
||||
{
|
||||
// These are only ever going to be depth values, so let's also show scaled to 16 bit.
|
||||
int z24 = pix & 0x00FFFFFF;
|
||||
int z16 = z24 - 0x800000 + 0x8000;
|
||||
_snwprintf(desc, 256, L"%d,%d: %d / %f", x, y, z16, z16 * (1.0f / 65535.0f));
|
||||
}
|
||||
break;
|
||||
|
||||
case GPU_DBG_FORMAT_24X_8BIT:
|
||||
_snwprintf(desc, 256, L"%d,%d: %d / %f", x, y, (pix >> 24) & 0xFF, ((pix >> 24) & 0xFF) * (1.0f / 255.0f));
|
||||
break;
|
||||
@@ -410,6 +419,15 @@ void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y,
|
||||
_snwprintf(desc, 256, L"%d,%d: %f / %f", x, y, *(float *)&pix, FromScaledDepth(*(float *)&pix));
|
||||
break;
|
||||
|
||||
case GPU_DBG_FORMAT_FLOAT_DIV_256:
|
||||
{
|
||||
double z = *(float *)&pix;
|
||||
int z24 = (int)(z * 16777215.0);
|
||||
int z16 = z24 - 0x800000 + 0x8000;
|
||||
_snwprintf(desc, 256, L"%d,%d: %d / %f", x, y, z16, (z - 0.5 + (1.0 / 512.0)) * 256.0);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
_snwprintf(desc, 256, L"Unexpected format");
|
||||
}
|
||||
|
||||
@@ -250,10 +250,18 @@ void SimpleGLWindow::Draw(const u8 *data, int w, int h, bool flipped, Format fmt
|
||||
} else if (fmt == FORMAT_FLOAT) {
|
||||
glfmt = GL_FLOAT;
|
||||
components = GL_RED;
|
||||
} else if (fmt == FORMAT_FLOAT_DIV_256) {
|
||||
glfmt = GL_UNSIGNED_INT;
|
||||
components = GL_RED;
|
||||
finalData = Reformat(data, fmt, w * h);
|
||||
} else if (fmt == FORMAT_24BIT_8X) {
|
||||
glfmt = GL_UNSIGNED_INT;
|
||||
components = GL_RED;
|
||||
finalData = Reformat(data, fmt, w * h);
|
||||
} else if (fmt == FORMAT_24BIT_8X_DIV_256) {
|
||||
glfmt = GL_UNSIGNED_INT;
|
||||
components = GL_RED;
|
||||
finalData = Reformat(data, fmt, w * h);
|
||||
} else if (fmt == FORMAT_24X_8BIT) {
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glfmt = GL_UNSIGNED_BYTE;
|
||||
@@ -545,6 +553,19 @@ const u8 *SimpleGLWindow::Reformat(const u8 *data, Format fmt, u32 numPixels) {
|
||||
for (u32 i = 0; i < numPixels; ++i) {
|
||||
reformatBuf_[i] = (data32[i] << 8) | ((data32[i] >> 16) & 0xFF);
|
||||
}
|
||||
} else if (fmt == FORMAT_24BIT_8X_DIV_256) {
|
||||
for (u32 i = 0; i < numPixels; ++i) {
|
||||
int z24 = data32[i] & 0x00FFFFFF;
|
||||
int z16 = z24 - 0x800000 + 0x8000;
|
||||
reformatBuf_[i] = (z16 << 16) | z16;
|
||||
}
|
||||
} else if (fmt == FORMAT_FLOAT_DIV_256) {
|
||||
for (u32 i = 0; i < numPixels; ++i) {
|
||||
double z = *(float *)&data32[i];
|
||||
int z24 = (int)(z * 16777215.0);
|
||||
int z16 = z24 - 0x800000 + 0x8000;
|
||||
reformatBuf_[i] = (z16 << 16) | z16;
|
||||
}
|
||||
} else if (fmt == FORMAT_24X_8BIT) {
|
||||
u8 *buf8 = (u8 *)reformatBuf_;
|
||||
for (u32 i = 0; i < numPixels; ++i) {
|
||||
|
||||
@@ -42,6 +42,9 @@ struct SimpleGLWindow {
|
||||
FORMAT_8BIT = 0x12,
|
||||
FORMAT_24BIT_8X = 0x13,
|
||||
FORMAT_24X_8BIT = 0x14,
|
||||
|
||||
FORMAT_FLOAT_DIV_256 = 0x18,
|
||||
FORMAT_24BIT_8X_DIV_256 = 0x1B,
|
||||
};
|
||||
|
||||
enum Flags {
|
||||
|
||||
Reference in new issue
Block a user