mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 10:40:01 +01:00
Merge branch 'master' into TemporaryHackishBranch
# Conflicts: # Windows/resource.h
This commit is contained in:
commit
2d0de56573
19 files changed
+355
-203
No files matched your search
+2
-2
@@ -84,7 +84,7 @@ if(NOT ANDROID)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT WIN32 AND VULKAN)
|
||||
if(VULKAN AND NOT WIN32 AND NOT ANDROID)
|
||||
IF (NOT Vulkan_FOUND)
|
||||
find_library(Vulkan_LIBRARY NAMES vulkan HINTS "$ENV{VULKAN_SDK}/lib" "${CMAKE_SOURCE_DIR}/ext/vulkan" REQUIRED)
|
||||
IF (Vulkan_LIBRARY)
|
||||
@@ -1676,7 +1676,7 @@ set(GlslangLibs glslang OGLCompiler OSDependent SPIRV SPVRemapper spirv-cross-gl
|
||||
target_link_libraries(${CoreLibName} Common native kirk cityhash sfmt19937 xbrz xxhash ${GlslangLibs}
|
||||
${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS})
|
||||
|
||||
if(VULKAN)
|
||||
if(VULKAN AND NOT ANDROID AND NOT WIN32)
|
||||
target_link_libraries(${CoreLibName} ${Vulkan_LIBRARY})
|
||||
endif()
|
||||
|
||||
|
||||
+1
-1
@@ -174,7 +174,7 @@ void AVIDump::AddFrame()
|
||||
u32 h = buf.GetHeight();
|
||||
CheckResolution(w, h);
|
||||
u8 *flipbuffer = nullptr;
|
||||
const u8 *buffer = ConvertBufferTo888RGB(buf, flipbuffer, w, h);
|
||||
const u8 *buffer = ConvertBufferToScreenshot(buf, false, flipbuffer, w, h);
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
|
||||
|
||||
+62
-22
@@ -125,12 +125,14 @@ static bool WriteScreenshotToPNG(png_imagep image, const char *filename, int con
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool ConvertPixelTo888RGB(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b, const void *buffer, int offset, bool rev) {
|
||||
static bool ConvertPixelTo8888RGBA(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b, u8 &a, const void *buffer, int offset, bool rev) {
|
||||
const u8 *buf8 = (const u8 *)buffer;
|
||||
const u16 *buf16 = (const u16 *)buffer;
|
||||
const u32 *buf32 = (const u32 *)buffer;
|
||||
const float *fbuf = (const float *)buffer;
|
||||
|
||||
// NOTE: a and r might be the same channel. This is used for RGB.
|
||||
|
||||
u32 src;
|
||||
double fsrc;
|
||||
switch (fmt) {
|
||||
@@ -139,6 +141,7 @@ static bool ConvertPixelTo888RGB(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b,
|
||||
if (rev) {
|
||||
src = bswap16(src);
|
||||
}
|
||||
a = 255;
|
||||
r = Convert5To8((src >> 0) & 0x1F);
|
||||
g = Convert6To8((src >> 5) & 0x3F);
|
||||
b = Convert5To8((src >> 11) & 0x1F);
|
||||
@@ -148,6 +151,7 @@ static bool ConvertPixelTo888RGB(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b,
|
||||
if (rev) {
|
||||
src = bswap16(src);
|
||||
}
|
||||
a = (src >> 15) ? 255 : 0;
|
||||
r = Convert5To8((src >> 0) & 0x1F);
|
||||
g = Convert5To8((src >> 5) & 0x1F);
|
||||
b = Convert5To8((src >> 10) & 0x1F);
|
||||
@@ -157,6 +161,7 @@ static bool ConvertPixelTo888RGB(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b,
|
||||
if (rev) {
|
||||
src = bswap16(src);
|
||||
}
|
||||
a = Convert4To8((src >> 12) & 0xF);
|
||||
r = Convert4To8((src >> 0) & 0xF);
|
||||
g = Convert4To8((src >> 4) & 0xF);
|
||||
b = Convert4To8((src >> 8) & 0xF);
|
||||
@@ -166,54 +171,62 @@ static bool ConvertPixelTo888RGB(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b,
|
||||
if (rev) {
|
||||
src = bswap32(src);
|
||||
}
|
||||
a = (src >> 24) & 0xFF;
|
||||
r = (src >> 0) & 0xFF;
|
||||
g = (src >> 8) & 0xFF;
|
||||
b = (src >> 16) & 0xFF;
|
||||
break;
|
||||
case GPU_DBG_FORMAT_FLOAT:
|
||||
fsrc = fbuf[offset];
|
||||
r = fsrc >= 1.0 ? 255 : (fsrc < 0.0 ? 0 : (int)(fsrc * 255.0));
|
||||
r = 255;
|
||||
g = 0;
|
||||
b = 0;
|
||||
a = fsrc >= 1.0 ? 255 : (fsrc < 0.0 ? 0 : (int)(fsrc * 255.0));
|
||||
break;
|
||||
case GPU_DBG_FORMAT_16BIT:
|
||||
src = buf16[offset];
|
||||
r = src >> 8;
|
||||
r = 255;
|
||||
g = 0;
|
||||
b = 0;
|
||||
a = src >> 8;
|
||||
break;
|
||||
case GPU_DBG_FORMAT_8BIT:
|
||||
src = buf8[offset];
|
||||
r = src;
|
||||
r = 255;
|
||||
g = 0;
|
||||
b = 0;
|
||||
a = src;
|
||||
break;
|
||||
case GPU_DBG_FORMAT_24BIT_8X:
|
||||
src = buf32[offset];
|
||||
r = (src >> 16) & 0xFF;
|
||||
r = 255;
|
||||
g = 0;
|
||||
b = 0;
|
||||
a = (src >> 16) & 0xFF;
|
||||
break;
|
||||
case GPU_DBG_FORMAT_24X_8BIT:
|
||||
src = buf32[offset];
|
||||
r = (src >> 24) & 0xFF;
|
||||
r = 255;
|
||||
g = 0;
|
||||
b = 0;
|
||||
a = (src >> 24) & 0xFF;
|
||||
break;
|
||||
case GPU_DBG_FORMAT_24BIT_8X_DIV_256:
|
||||
src = buf32[offset]& 0x00FFFFFF;
|
||||
src = src - 0x800000 + 0x8000;
|
||||
r = (src >> 8) & 0xFF;
|
||||
r = 255;
|
||||
g = 0;
|
||||
b = 0;
|
||||
a = (src >> 8) & 0xFF;
|
||||
break;
|
||||
case GPU_DBG_FORMAT_FLOAT_DIV_256:
|
||||
fsrc = fbuf[offset];
|
||||
src = (int)(fsrc * 16777215.0);
|
||||
src = src - 0x800000 + 0x8000;
|
||||
r = (src >> 8) & 0xFF;
|
||||
r = 255;
|
||||
g = 0;
|
||||
b = 0;
|
||||
a = (src >> 8) & 0xFF;
|
||||
break;
|
||||
default:
|
||||
_assert_msg_(SYSTEM, false, "Unsupported framebuffer format for screenshot: %d", fmt);
|
||||
@@ -223,24 +236,27 @@ static bool ConvertPixelTo888RGB(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b,
|
||||
return true;
|
||||
}
|
||||
|
||||
const u8 *ConvertBufferTo888RGB(const GPUDebugBuffer &buf, u8 *&temp, u32 &w, u32 &h) {
|
||||
const u8 *ConvertBufferToScreenshot(const GPUDebugBuffer &buf, bool alpha, u8 *&temp, u32 &w, u32 &h) {
|
||||
int pixelSize = alpha ? 4 : 3;
|
||||
GPUDebugBufferFormat nativeFmt = alpha ? GPU_DBG_FORMAT_8888 : GPU_DBG_FORMAT_888_RGB;
|
||||
|
||||
w = std::min(w, buf.GetStride());
|
||||
h = std::min(h, buf.GetHeight());
|
||||
|
||||
// The temp buffer will be freed by the caller if set, and can be the return value.
|
||||
if (buf.GetFlipped() || buf.GetFormat() != GPU_DBG_FORMAT_888_RGB) {
|
||||
temp = new u8[3 * w * h];
|
||||
if (buf.GetFlipped() || buf.GetFormat() != nativeFmt) {
|
||||
temp = new u8[pixelSize * w * h];
|
||||
} else {
|
||||
temp = nullptr;
|
||||
}
|
||||
|
||||
const u8 *buffer = buf.GetData();
|
||||
if (buf.GetFlipped() && buf.GetFormat() == GPU_DBG_FORMAT_888_RGB) {
|
||||
if (buf.GetFlipped() && buf.GetFormat() == nativeFmt) {
|
||||
// Silly OpenGL reads upside down, we flip to another buffer for simplicity.
|
||||
for (u32 y = 0; y < h; y++) {
|
||||
memcpy(temp + y * w * 3, buffer + (buf.GetHeight() - y - 1) * buf.GetStride() * 3, w * 3);
|
||||
memcpy(temp + y * w * pixelSize, buffer + (buf.GetHeight() - y - 1) * buf.GetStride() * pixelSize, w * pixelSize);
|
||||
}
|
||||
} else if (buf.GetFormat() < GPU_DBG_FORMAT_FLOAT) {
|
||||
} else if (buf.GetFormat() < GPU_DBG_FORMAT_FLOAT && buf.GetFormat() != nativeFmt) {
|
||||
// Let's boil it down to how we need to interpret the bits.
|
||||
int baseFmt = buf.GetFormat() & ~(GPU_DBG_FORMAT_REVERSE_FLAG | GPU_DBG_FORMAT_BRSWAP_FLAG);
|
||||
bool rev = (buf.GetFormat() & GPU_DBG_FORMAT_REVERSE_FLAG) != 0;
|
||||
@@ -252,21 +268,22 @@ const u8 *ConvertBufferTo888RGB(const GPUDebugBuffer &buf, u8 *&temp, u32 &w, u3
|
||||
for (u32 x = 0; x < w; x++) {
|
||||
u8 *dst;
|
||||
if (flip) {
|
||||
dst = &temp[(h - y - 1) * w * 3 + x * 3];
|
||||
dst = &temp[(h - y - 1) * w * pixelSize + x * pixelSize];
|
||||
} else {
|
||||
dst = &temp[y * w * 3 + x * 3];
|
||||
dst = &temp[y * w * pixelSize + x * pixelSize];
|
||||
}
|
||||
|
||||
u8 &r = brswap ? dst[2] : dst[0];
|
||||
u8 &g = dst[1];
|
||||
u8 &b = brswap ? dst[0] : dst[2];
|
||||
u8 &a = alpha ? dst[3] : r;
|
||||
|
||||
if (!ConvertPixelTo888RGB(GPUDebugBufferFormat(baseFmt), r, g, b, buffer, y * buf.GetStride() + x, rev)) {
|
||||
if (!ConvertPixelTo8888RGBA(GPUDebugBufferFormat(baseFmt), r, g, b, a, buffer, y * buf.GetStride() + x, rev)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (buf.GetFormat() != GPU_DBG_FORMAT_888_RGB) {
|
||||
} else if (buf.GetFormat() != nativeFmt) {
|
||||
bool flip = buf.GetFlipped();
|
||||
|
||||
// This is pretty inefficient.
|
||||
@@ -274,12 +291,13 @@ const u8 *ConvertBufferTo888RGB(const GPUDebugBuffer &buf, u8 *&temp, u32 &w, u3
|
||||
for (u32 x = 0; x < w; x++) {
|
||||
u8 *dst;
|
||||
if (flip) {
|
||||
dst = &temp[(h - y - 1) * w * 3 + x * 3];
|
||||
dst = &temp[(h - y - 1) * w * pixelSize + x * pixelSize];
|
||||
} else {
|
||||
dst = &temp[y * w * 3 + x * 3];
|
||||
dst = &temp[y * w * pixelSize + x * pixelSize];
|
||||
}
|
||||
|
||||
if (!ConvertPixelTo888RGB(buf.GetFormat(), dst[0], dst[1], dst[2], buffer, y * buf.GetStride() + x, false)) {
|
||||
u8 &a = alpha ? dst[3] : dst[0];
|
||||
if (!ConvertPixelTo8888RGBA(buf.GetFormat(), dst[0], dst[1], dst[2], a, buffer, y * buf.GetStride() + x, false)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -316,7 +334,7 @@ bool TakeGameScreenshot(const char *filename, ScreenshotFormat fmt, ScreenshotTy
|
||||
|
||||
u8 *flipbuffer = nullptr;
|
||||
if (success) {
|
||||
const u8 *buffer = ConvertBufferTo888RGB(buf, flipbuffer, w, h);
|
||||
const u8 *buffer = ConvertBufferToScreenshot(buf, false, flipbuffer, w, h);
|
||||
success = buffer != nullptr;
|
||||
if (success) {
|
||||
if (width)
|
||||
@@ -364,3 +382,25 @@ bool Save888RGBScreenshot(const char *filename, ScreenshotFormat fmt, const u8 *
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Save8888RGBAScreenshot(const char *filename, const u8 *buffer, int w, int h) {
|
||||
#ifdef USING_QT_UI
|
||||
QImage image(buffer, w, h, QImage::Format_RGBA8888);
|
||||
return image.save(filename, "PNG");
|
||||
#else
|
||||
png_image png;
|
||||
memset(&png, 0, sizeof(png));
|
||||
png.version = PNG_IMAGE_VERSION;
|
||||
png.format = PNG_FORMAT_RGBA;
|
||||
png.width = w;
|
||||
png.height = h;
|
||||
bool success = WriteScreenshotToPNG(&png, filename, 0, buffer, w * 4, nullptr);
|
||||
png_image_free(&png);
|
||||
|
||||
if (png.warning_or_error >= 2) {
|
||||
ERROR_LOG(SYSTEM, "Saving screenshot to PNG produced errors.");
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
#endif
|
||||
}
|
||||
+2
-1
@@ -33,8 +33,9 @@ enum ScreenshotType {
|
||||
SCREENSHOT_RENDER,
|
||||
};
|
||||
|
||||
const u8 *ConvertBufferTo888RGB(const GPUDebugBuffer &buf, u8 *&temp, u32 &w, u32 &h);
|
||||
const u8 *ConvertBufferToScreenshot(const GPUDebugBuffer &buf, bool alpha, u8 *&temp, u32 &w, u32 &h);
|
||||
|
||||
// Can only be used while in game.
|
||||
bool TakeGameScreenshot(const char *filename, ScreenshotFormat fmt, ScreenshotType type, int *width = nullptr, int *height = nullptr, int maxRes = -1);
|
||||
bool Save888RGBScreenshot(const char *filename, ScreenshotFormat fmt, const u8 *bufferRGB888, int w, int h);
|
||||
bool Save8888RGBAScreenshot(const char *filename, const u8 *bufferRGBA8888, int w, int h);
|
||||
@@ -489,7 +489,7 @@ u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr,
|
||||
}
|
||||
|
||||
bool DrawEngineCommon::ApplyShaderBlending() {
|
||||
if (gstate_c.featureFlags & GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH) {
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1970,8 +1970,11 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32
|
||||
} else {
|
||||
buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT, flipY);
|
||||
}
|
||||
draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w);
|
||||
return true;
|
||||
// No need to free on failure, that's the caller's job (it likely will reuse a buffer.)
|
||||
bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w);
|
||||
// That may have unbound the framebuffer, rebind to avoid crashes when debugging.
|
||||
RebindFramebuffer();
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool FramebufferManagerCommon::GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) {
|
||||
@@ -1996,21 +1999,22 @@ bool FramebufferManagerCommon::GetStencilbuffer(u32 fb_address, int fb_stride, G
|
||||
}
|
||||
|
||||
bool flipY = (g_Config.iGPUBackend == GPU_BACKEND_OPENGL && !useBufferedRendering_) ? true : false;
|
||||
// No need to free on failure, the caller/destructor will do that. Usually this is a reused buffer, anyway.
|
||||
buffer.Allocate(w, h, GPU_DBG_FORMAT_8BIT, flipY);
|
||||
if (draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_STENCIL_BIT, 0, 0, w,h, Draw::DataFormat::S8, buffer.GetData(), w)) {
|
||||
return true;
|
||||
} else {
|
||||
buffer.Free();
|
||||
return false;
|
||||
}
|
||||
bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_STENCIL_BIT, 0, 0, w,h, Draw::DataFormat::S8, buffer.GetData(), w);
|
||||
// That may have unbound the framebuffer, rebind to avoid crashes when debugging.
|
||||
RebindFramebuffer();
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool FramebufferManagerCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
|
||||
int w, h;
|
||||
draw_->GetFramebufferDimensions(nullptr, &w, &h);
|
||||
buffer.Allocate(w, h, GE_FORMAT_8888, false, true);
|
||||
draw_->CopyFramebufferToMemorySync(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), w);
|
||||
return true;
|
||||
bool retval = draw_->CopyFramebufferToMemorySync(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), w);
|
||||
// That may have unbound the framebuffer, rebind to avoid crashes when debugging.
|
||||
RebindFramebuffer();
|
||||
return retval;
|
||||
}
|
||||
|
||||
// This function takes an already correctly-sized framebuffer and packs it into RAM.
|
||||
@@ -2113,7 +2117,7 @@ void FramebufferManagerCommon::RebindFramebuffer() {
|
||||
if (currentRenderVfb_ && currentRenderVfb_->fbo) {
|
||||
draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP });
|
||||
} else {
|
||||
// Should this even happen?
|
||||
// Should this even happen? It could while debugging, but maybe we can just skip binding at all.
|
||||
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP });
|
||||
}
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE);
|
||||
|
||||
@@ -303,7 +303,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
|
||||
case GE_DSTBLEND_DOUBLESRCALPHA:
|
||||
// We can't technically do this correctly (due to clamping) without reading the dst color.
|
||||
// Using a copy isn't accurate either, though, when there's overlap.
|
||||
if (gstate_c.featureFlags & GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH))
|
||||
return !allowShaderBlend ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
|
||||
return REPLACE_BLEND_PRE_SRC_2X_ALPHA;
|
||||
|
||||
@@ -445,14 +445,14 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
|
||||
case GE_DSTBLEND_DOUBLESRCALPHA:
|
||||
if (funcA == GE_SRCBLEND_SRCALPHA || funcA == GE_SRCBLEND_INVSRCALPHA) {
|
||||
// Can't safely double alpha, will clamp. However, a copy may easily be worse due to overlap.
|
||||
if (gstate_c.featureFlags & GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH))
|
||||
return !allowShaderBlend ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
|
||||
return REPLACE_BLEND_PRE_SRC_2X_ALPHA;
|
||||
} else {
|
||||
// This means dst alpha/color is used in the src factor.
|
||||
// Unfortunately, copying here causes overlap problems in Silent Hill games (it seems?)
|
||||
// We will just hope that doubling alpha for the dst factor will not clamp too badly.
|
||||
if (gstate_c.featureFlags & GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH))
|
||||
return !allowShaderBlend ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
|
||||
return REPLACE_BLEND_2X_ALPHA;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, uint64_t *uniform
|
||||
|
||||
if (gl_extensions.IsGLES) {
|
||||
// ES doesn't support dual source alpha :(
|
||||
if (gstate_c.featureFlags & GPU_SUPPORTS_GLSL_ES_300) {
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300)) {
|
||||
WRITE(p, "#version 300 es\n"); // GLSL ES 3.0
|
||||
fragColor0 = "fragColor0";
|
||||
texture = "texture";
|
||||
@@ -91,8 +91,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, uint64_t *uniform
|
||||
highpFog = (gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_BAD) ? true : false;
|
||||
highpTexcoord = highpFog;
|
||||
|
||||
if (gstate_c.featureFlags & GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH) {
|
||||
if ((gstate_c.featureFlags & GPU_SUPPORTS_GLSL_ES_300) != 0 && gl_extensions.EXT_shader_framebuffer_fetch) {
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)) {
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300) && gl_extensions.EXT_shader_framebuffer_fetch) {
|
||||
WRITE(p, "#extension GL_EXT_shader_framebuffer_fetch : require\n");
|
||||
lastFragData = "fragColor0";
|
||||
} else if (gl_extensions.EXT_shader_framebuffer_fetch) {
|
||||
@@ -535,7 +535,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, uint64_t *uniform
|
||||
if (replaceBlend == REPLACE_BLEND_COPY_FBO) {
|
||||
// If we have NV_shader_framebuffer_fetch / EXT_shader_framebuffer_fetch, we skip the blit.
|
||||
// We can just read the prev value more directly.
|
||||
if (gstate_c.featureFlags & GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH) {
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)) {
|
||||
WRITE(p, " lowp vec4 destColor = %s;\n", lastFragData);
|
||||
} else if (!texelFetch) {
|
||||
WRITE(p, " lowp vec4 destColor = %s(fbotex, gl_FragCoord.xy * u_fbotexSize.xy);\n", texture);
|
||||
|
||||
@@ -175,7 +175,8 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
||||
|
||||
if (g_Config.bHardwareTessellation) {
|
||||
// Disable hardware tessellation if device is unsupported.
|
||||
if (!gstate_c.SupportsAll(GPU_SUPPORTS_INSTANCE_RENDERING | GPU_SUPPORTS_VERTEX_TEXTURE_FETCH | GPU_SUPPORTS_TEXTURE_FLOAT)) {
|
||||
bool hasTexelFetch = gl_extensions.GLES3 || (!gl_extensions.IsGLES && gl_extensions.VersionGEThan(3, 3, 0)) || gl_extensions.EXT_gpu_shader4;
|
||||
if (!gstate_c.SupportsAll(GPU_SUPPORTS_INSTANCE_RENDERING | GPU_SUPPORTS_VERTEX_TEXTURE_FETCH | GPU_SUPPORTS_TEXTURE_FLOAT) || !hasTexelFetch) {
|
||||
// TODO: Check unsupported device name list.(Above gpu features are supported but it has issues with weak gpu, memory, shader compiler etc...)
|
||||
g_Config.bHardwareTessellation = false;
|
||||
ERROR_LOG(G3D, "Hardware Tessellation is unsupported, falling back to software tessellation");
|
||||
|
||||
@@ -114,7 +114,7 @@ LinkedShader::LinkedShader(VShaderID VSID, Shader *vs, FShaderID FSID, Shader *f
|
||||
glBindAttribLocation(program, ATTR_COLOR1, "color1");
|
||||
|
||||
#if !defined(USING_GLES2)
|
||||
if (gstate_c.featureFlags & GPU_SUPPORTS_DUALSOURCE_BLEND) {
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_DUALSOURCE_BLEND)) {
|
||||
// Dual source alpha
|
||||
glBindFragDataLocationIndexed(program, 0, 0, "fragColor0");
|
||||
glBindFragDataLocationIndexed(program, 0, 1, "fragColor1");
|
||||
@@ -123,7 +123,7 @@ LinkedShader::LinkedShader(VShaderID VSID, Shader *vs, FShaderID FSID, Shader *f
|
||||
}
|
||||
#elif !defined(IOS)
|
||||
if (gl_extensions.GLES3) {
|
||||
if (gstate_c.featureFlags & GPU_SUPPORTS_DUALSOURCE_BLEND) {
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_DUALSOURCE_BLEND)) {
|
||||
glBindFragDataLocationIndexedEXT(program, 0, 0, "fragColor0");
|
||||
glBindFragDataLocationIndexedEXT(program, 0, 1, "fragColor1");
|
||||
}
|
||||
|
||||
+4
-2
@@ -36,15 +36,17 @@ SDLJoystick *joystick = NULL;
|
||||
#include "Common/Vulkan/VulkanDebug.h"
|
||||
#include "math.h"
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
#include "SDL_syswm.h"
|
||||
#endif
|
||||
|
||||
#if defined(VK_USE_PLATFORM_XLIB_KHR)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include "SDL_syswm.h"
|
||||
#elif defined(VK_USE_PLATFORM_XCB_KHR)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include "SDL_syswm.h"
|
||||
#endif
|
||||
|
||||
#if defined(USING_EGL)
|
||||
|
||||
@@ -99,8 +99,9 @@ bool CheckSupportInstancedTessellationGLES() {
|
||||
bool instanceRendering = gl_extensions.GLES3 || (canUseInstanceID && canDefInstanceID);
|
||||
|
||||
bool textureFloat = gl_extensions.ARB_texture_float || gl_extensions.OES_texture_float;
|
||||
bool hasTexelFetch = gl_extensions.GLES3 || (!gl_extensions.IsGLES && gl_extensions.VersionGEThan(3, 3, 0)) || gl_extensions.EXT_gpu_shader4;
|
||||
|
||||
return instanceRendering && vertexTexture && textureFloat;
|
||||
return instanceRendering && vertexTexture && textureFloat && hasTexelFetch;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -157,16 +157,27 @@ void CGEDebugger::SetupPreviews() {
|
||||
PrimaryPreviewHover(x, y);
|
||||
});
|
||||
primaryWindow->SetRightClickMenu(subMenu, [&] (int cmd) {
|
||||
HMENU subMenu = GetSubMenu(g_hPopupMenus, POPUP_SUBMENU_ID_GEDBG_PREVIEW);
|
||||
switch (cmd) {
|
||||
case 0:
|
||||
// Setup.
|
||||
CheckMenuItem(subMenu, ID_GEDBG_ENABLE_PREVIEW, MF_BYCOMMAND | ((previewsEnabled_ & 1) ? MF_CHECKED : MF_UNCHECKED));
|
||||
break;
|
||||
case ID_GEDBG_EXPORT_IMAGE:
|
||||
PreviewExport(primaryBuffer_);
|
||||
break;
|
||||
case ID_GEDBG_ENABLE_PREVIEW:
|
||||
previewsEnabled_ ^= 1;
|
||||
primaryWindow->Redraw();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
primaryWindow->SetRedrawCallback([&] {
|
||||
HandleRedraw(1);
|
||||
});
|
||||
primaryWindow->Clear();
|
||||
}
|
||||
if (secondWindow == nullptr) {
|
||||
@@ -178,16 +189,27 @@ void CGEDebugger::SetupPreviews() {
|
||||
SecondPreviewHover(x, y);
|
||||
});
|
||||
secondWindow->SetRightClickMenu(subMenu, [&] (int cmd) {
|
||||
HMENU subMenu = GetSubMenu(g_hPopupMenus, POPUP_SUBMENU_ID_GEDBG_PREVIEW);
|
||||
switch (cmd) {
|
||||
case 0:
|
||||
// Setup.
|
||||
CheckMenuItem(subMenu, ID_GEDBG_ENABLE_PREVIEW, MF_BYCOMMAND | ((previewsEnabled_ & 2) ? MF_CHECKED : MF_UNCHECKED));
|
||||
break;
|
||||
case ID_GEDBG_EXPORT_IMAGE:
|
||||
PreviewExport(secondBuffer_);
|
||||
break;
|
||||
case ID_GEDBG_ENABLE_PREVIEW:
|
||||
previewsEnabled_ ^= 2;
|
||||
secondWindow->Redraw();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
secondWindow->SetRedrawCallback([&] {
|
||||
HandleRedraw(2);
|
||||
});
|
||||
secondWindow->Clear();
|
||||
}
|
||||
}
|
||||
@@ -229,13 +251,18 @@ void CGEDebugger::PreviewExport(const GPUDebugBuffer *dbgBuffer) {
|
||||
std::string fn;
|
||||
if (W32Util::BrowseForFileName(false, GetDlgHandle(), L"Save Preview Image...", nullptr, filter, L"png", fn)) {
|
||||
ScreenshotFormat fmt = fn.find(".jpg") != fn.npos ? ScreenshotFormat::JPG : ScreenshotFormat::PNG;
|
||||
bool saveAlpha = fmt == ScreenshotFormat::PNG;
|
||||
|
||||
u8 *flipbuffer = nullptr;
|
||||
u32 w = (u32)-1;
|
||||
u32 h = (u32)-1;
|
||||
const u8 *buffer = ConvertBufferTo888RGB(*dbgBuffer, flipbuffer, w, h);
|
||||
const u8 *buffer = ConvertBufferToScreenshot(*dbgBuffer, saveAlpha, flipbuffer, w, h);
|
||||
if (buffer != nullptr) {
|
||||
Save888RGBScreenshot(fn.c_str(), fmt, buffer, w, h);
|
||||
if (saveAlpha) {
|
||||
Save8888RGBAScreenshot(fn.c_str(), buffer, w, h);
|
||||
} else {
|
||||
Save888RGBScreenshot(fn.c_str(), fmt, buffer, w, h);
|
||||
}
|
||||
}
|
||||
delete [] flipbuffer;
|
||||
}
|
||||
@@ -253,19 +280,18 @@ void CGEDebugger::UpdatePreviews() {
|
||||
state = gpuDebug->GetGState();
|
||||
}
|
||||
|
||||
updating_ = true;
|
||||
UpdateTextureLevel(textureLevel_);
|
||||
UpdatePrimaryPreview(state);
|
||||
UpdateSecondPreview(state);
|
||||
|
||||
u32 primOp = PrimPreviewOp();
|
||||
if (primOp != 0) {
|
||||
UpdatePrimPreview(primOp, 3);
|
||||
}
|
||||
|
||||
DisplayList list;
|
||||
if (gpuDebug != nullptr && gpuDebug->GetCurrentDisplayList(list)) {
|
||||
const u32 op = Memory::Read_U32(list.pc);
|
||||
const u32 cmd = op >> 24;
|
||||
// TODO: Bezier/spline?
|
||||
if (cmd == GE_CMD_PRIM && !showClut_) {
|
||||
UpdatePrimPreview(op);
|
||||
}
|
||||
|
||||
displayList->setDisplayList(list);
|
||||
}
|
||||
|
||||
@@ -277,6 +303,7 @@ void CGEDebugger::UpdatePreviews() {
|
||||
matrices->Update();
|
||||
lists->Update();
|
||||
watch->Update();
|
||||
updating_ = false;
|
||||
}
|
||||
|
||||
u32 CGEDebugger::TexturePreviewFlags(const GPUgstate &state) {
|
||||
|
||||
@@ -70,8 +70,10 @@ private:
|
||||
void UpdatePreviews();
|
||||
void UpdatePrimaryPreview(const GPUgstate &state);
|
||||
void UpdateSecondPreview(const GPUgstate &state);
|
||||
void UpdatePrimPreview(u32 op);
|
||||
u32 PrimPreviewOp();
|
||||
void UpdatePrimPreview(u32 op, int which);
|
||||
void CleanupPrimPreview();
|
||||
void HandleRedraw(int which);
|
||||
void UpdateSize(WORD width, WORD height);
|
||||
void SavePosition();
|
||||
void SetBreakNext(BreakNextType type);
|
||||
@@ -106,6 +108,8 @@ private:
|
||||
const GPUDebugBuffer *primaryBuffer_ = nullptr;
|
||||
const GPUDebugBuffer *secondBuffer_ = nullptr;
|
||||
|
||||
bool updating_ = false;
|
||||
int previewsEnabled_ = 3;
|
||||
int minWidth_;
|
||||
int minHeight_;
|
||||
};
|
||||
@@ -68,8 +68,7 @@ static const char basic_vs[] =
|
||||
"}\n";
|
||||
|
||||
SimpleGLWindow::SimpleGLWindow(HWND wnd)
|
||||
: hWnd_(wnd), valid_(false), drawProgram_(nullptr), vao_(0), tex_(0), flags_(0), zoom_(false),
|
||||
dragging_(false), offsetX_(0), offsetY_(0), reformatBuf_(nullptr), hoverCallback_(nullptr) {
|
||||
: hWnd_(wnd) {
|
||||
SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR) this);
|
||||
}
|
||||
|
||||
@@ -365,10 +364,23 @@ void SimpleGLWindow::GetContentSize(float &x, float &y, float &fw, float &fh) {
|
||||
void SimpleGLWindow::Redraw(bool andSwap) {
|
||||
DrawChecker();
|
||||
|
||||
if (tw_ == 0 && th_ == 0) {
|
||||
auto swapWithCallback = [andSwap, this]() {
|
||||
if (andSwap) {
|
||||
Swap();
|
||||
swapped_ = false;
|
||||
if (redrawCallback_ && !inRedrawCallback_) {
|
||||
inRedrawCallback_ = true;
|
||||
redrawCallback_();
|
||||
inRedrawCallback_ = false;
|
||||
}
|
||||
// In case the callback swaps, don't do it twice.
|
||||
if (!swapped_) {
|
||||
Swap();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (tw_ == 0 && th_ == 0) {
|
||||
swapWithCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -412,7 +424,7 @@ void SimpleGLWindow::Redraw(bool andSwap) {
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, vao_ ? 0 : indices);
|
||||
|
||||
if (andSwap) {
|
||||
Swap();
|
||||
swapWithCallback();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,7 +435,9 @@ void SimpleGLWindow::Clear() {
|
||||
}
|
||||
|
||||
void SimpleGLWindow::Begin() {
|
||||
Redraw(false);
|
||||
if (!inRedrawCallback_) {
|
||||
Redraw(false);
|
||||
}
|
||||
|
||||
if (vao_) {
|
||||
glBindVertexArray(0);
|
||||
@@ -549,6 +563,7 @@ bool SimpleGLWindow::RightClick(int mouseX, int mouseY) {
|
||||
POINT pt{mouseX, mouseY};
|
||||
ClientToScreen(hWnd_, &pt);
|
||||
|
||||
rightClickCallback_(0);
|
||||
int result = TrackPopupMenuEx(rightClickMenu_, TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hWnd_, 0);
|
||||
if (result != 0) {
|
||||
rightClickCallback_(result);
|
||||
|
||||
@@ -81,6 +81,7 @@ struct SimpleGLWindow {
|
||||
}
|
||||
|
||||
void Swap() {
|
||||
swapped_ = true;
|
||||
SwapBuffers(hDC_);
|
||||
}
|
||||
|
||||
@@ -106,10 +107,15 @@ struct SimpleGLWindow {
|
||||
|
||||
void GetContentSize(float &x, float &y, float &fw, float &fh);
|
||||
|
||||
void SetRedrawCallback(std::function<void()> callback) {
|
||||
redrawCallback_ = callback;
|
||||
}
|
||||
|
||||
void SetHoverCallback(std::function<void(int, int)> hoverCallback) {
|
||||
hoverCallback_ = hoverCallback;
|
||||
}
|
||||
|
||||
// Called first with 0 that it's opening, then the selected item.
|
||||
void SetRightClickMenu(HMENU menu, std::function<void(int)> callback) {
|
||||
rightClickCallback_ = callback;
|
||||
rightClickMenu_ = menu;
|
||||
@@ -134,7 +140,7 @@ protected:
|
||||
HWND hWnd_;
|
||||
HDC hDC_;
|
||||
HGLRC hGLRC_;
|
||||
bool valid_;
|
||||
bool valid_ = false;
|
||||
// Width and height of the window.
|
||||
int w_;
|
||||
int h_;
|
||||
@@ -143,25 +149,28 @@ protected:
|
||||
int th_;
|
||||
bool tflipped_;
|
||||
|
||||
GLSLProgram *drawProgram_;
|
||||
GLuint vao_;
|
||||
GLuint ibuf_;
|
||||
GLuint vbuf_;
|
||||
GLuint checker_;
|
||||
GLuint tex_;
|
||||
u32 flags_;
|
||||
GLSLProgram *drawProgram_ = nullptr;
|
||||
GLuint vao_ = 0;
|
||||
GLuint ibuf_ = 0;
|
||||
GLuint vbuf_ = 0;
|
||||
GLuint checker_ = 0;
|
||||
GLuint tex_ = 0;
|
||||
u32 flags_ = 0;
|
||||
// Disable shrink (toggled by double click.)
|
||||
bool zoom_;
|
||||
bool dragging_;
|
||||
bool zoom_ = false;
|
||||
bool dragging_ = false;
|
||||
bool inRedrawCallback_ = false;
|
||||
bool swapped_ = false;
|
||||
int dragStartX_;
|
||||
int dragStartY_;
|
||||
u32 dragLastUpdate_;
|
||||
// Offset to position the texture is drawn at.
|
||||
int offsetX_;
|
||||
int offsetY_;
|
||||
u32 *reformatBuf_;
|
||||
u32 reformatBufSize_;
|
||||
int offsetX_ = 0;
|
||||
int offsetY_ = 0;
|
||||
u32 *reformatBuf_ = nullptr;
|
||||
u32 reformatBufSize_ = 0;
|
||||
|
||||
std::function<void()> redrawCallback_;
|
||||
std::function<void(int, int)> hoverCallback_;
|
||||
std::function<void(int)> rightClickCallback_;
|
||||
HMENU rightClickMenu_;
|
||||
|
||||
@@ -151,7 +151,21 @@ static void ExpandRectangles(std::vector<GPUDebugVertex> &vertices, std::vector<
|
||||
count *= 3;
|
||||
}
|
||||
|
||||
void CGEDebugger::UpdatePrimPreview(u32 op) {
|
||||
u32 CGEDebugger::PrimPreviewOp() {
|
||||
DisplayList list;
|
||||
if (gpuDebug != nullptr && gpuDebug->GetCurrentDisplayList(list)) {
|
||||
const u32 op = Memory::Read_U32(list.pc);
|
||||
const u32 cmd = op >> 24;
|
||||
// TODO: Bezier/spline?
|
||||
if (cmd == GE_CMD_PRIM && !showClut_) {
|
||||
return op;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CGEDebugger::UpdatePrimPreview(u32 op, int which) {
|
||||
const u32 prim_type = (op >> 16) & 0x7;
|
||||
int count = op & 0xFFFF;
|
||||
if (prim_type >= 7) {
|
||||
@@ -162,7 +176,8 @@ void CGEDebugger::UpdatePrimPreview(u32 op) {
|
||||
ERROR_LOG(G3D, "Invalid debugging environment, shutting down?");
|
||||
return;
|
||||
}
|
||||
if (count == 0) {
|
||||
which &= previewsEnabled_;
|
||||
if (count == 0 || which == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -182,17 +197,6 @@ void CGEDebugger::UpdatePrimPreview(u32 op) {
|
||||
float fw, fh;
|
||||
float x, y;
|
||||
|
||||
primaryWindow->Begin();
|
||||
primaryWindow->GetContentSize(x, y, fw, fh);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glViewport((GLint)x, (GLint)y, (GLsizei)fw, (GLsizei)fh);
|
||||
glScissor((GLint)x, (GLint)y, (GLsizei)fw, (GLsizei)fh);
|
||||
BindPreviewProgram(previewProgram);
|
||||
|
||||
// TODO: Probably there's a better way and place to do this.
|
||||
u16 minIndex = 0;
|
||||
u16 maxIndex = count - 1;
|
||||
@@ -209,124 +213,155 @@ void CGEDebugger::UpdatePrimPreview(u32 op) {
|
||||
}
|
||||
}
|
||||
|
||||
const float invTexWidth = 1.0f / gstate_c.curTextureWidth;
|
||||
const float invTexHeight = 1.0f / gstate_c.curTextureHeight;
|
||||
auto wrapCoord = [](float &coord) {
|
||||
if (coord < 0.0f) {
|
||||
coord += ceilf(-coord);
|
||||
}
|
||||
if (coord > 1.0f) {
|
||||
coord -= floorf(coord);
|
||||
}
|
||||
};
|
||||
|
||||
const float invTexWidth = 1.0f / gpuDebug->GetGState().getTextureWidth(0);
|
||||
const float invTexHeight = 1.0f / gpuDebug->GetGState().getTextureHeight(0);
|
||||
const float invRealTexWidth = 1.0f / gstate_c.curTextureWidth;
|
||||
const float invRealTexHeight = 1.0f / gstate_c.curTextureHeight;
|
||||
bool clampS = gpuDebug->GetGState().isTexCoordClampedS();
|
||||
bool clampT = gpuDebug->GetGState().isTexCoordClampedT();
|
||||
for (u16 i = minIndex; i <= maxIndex; ++i) {
|
||||
vertices[i].u *= invTexWidth;
|
||||
vertices[i].v *= invTexHeight;
|
||||
if (vertices[i].u > 1.0f || vertices[i].u < 0.0f)
|
||||
vertices[i].u -= floor(vertices[i].u);
|
||||
if (vertices[i].v > 1.0f || vertices[i].v < 0.0f)
|
||||
vertices[i].v -= floor(vertices[i].v);
|
||||
if (!clampS)
|
||||
wrapCoord(vertices[i].u);
|
||||
if (!clampT)
|
||||
wrapCoord(vertices[i].v);
|
||||
}
|
||||
|
||||
if (previewVao == 0 && gl_extensions.ARB_vertex_array_object) {
|
||||
glGenVertexArrays(1, &previewVao);
|
||||
glBindVertexArray(previewVao);
|
||||
glEnableVertexAttribArray(previewProgram->a_position);
|
||||
if (which & 1) {
|
||||
primaryWindow->Begin();
|
||||
primaryWindow->GetContentSize(x, y, fw, fh);
|
||||
|
||||
glGenBuffers(1, &ibuf);
|
||||
glGenBuffers(1, &vbuf);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
// The surface is upside down, so vertical offsets are negated.
|
||||
glViewport((GLint)x, (GLint)-(y + fh - primaryWindow->Height()), (GLsizei)fw, (GLsizei)fh);
|
||||
glScissor((GLint)x, (GLint)-(y + fh - primaryWindow->Height()), (GLsizei)fw, (GLsizei)fh);
|
||||
BindPreviewProgram(previewProgram);
|
||||
|
||||
glVertexAttribPointer(previewProgram->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (void *)(2 * sizeof(float)));
|
||||
if (previewVao == 0 && gl_extensions.ARB_vertex_array_object) {
|
||||
glGenVertexArrays(1, &previewVao);
|
||||
glBindVertexArray(previewVao);
|
||||
glEnableVertexAttribArray(previewProgram->a_position);
|
||||
|
||||
glGenBuffers(1, &ibuf);
|
||||
glGenBuffers(1, &vbuf);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
|
||||
|
||||
glVertexAttribPointer(previewProgram->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (void *)(2 * sizeof(float)));
|
||||
}
|
||||
|
||||
if (vbuf != 0) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GPUDebugVertex), vertices.data(), GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
if (ibuf != 0 && !indices.empty()) {
|
||||
glBindVertexArray(previewVao);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(u16), indices.data(), GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
float scale[] = {
|
||||
480.0f / (float)PSP_CoreParameter().renderWidth,
|
||||
272.0f / (float)PSP_CoreParameter().renderHeight,
|
||||
};
|
||||
|
||||
Matrix4x4 ortho;
|
||||
ortho.setOrtho(-(float)gstate_c.curRTOffsetX, (primaryWindow->TexWidth() - (int)gstate_c.curRTOffsetX) * scale[0], primaryWindow->TexHeight() * scale[1], 0, -1, 1);
|
||||
glUniformMatrix4fv(previewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr());
|
||||
if (previewVao != 0) {
|
||||
glBindVertexArray(previewVao);
|
||||
} else {
|
||||
glEnableVertexAttribArray(previewProgram->a_position);
|
||||
glVertexAttribPointer(previewProgram->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data() + 2);
|
||||
}
|
||||
|
||||
if (indices.empty()) {
|
||||
glDrawArrays(glprim[prim], 0, count);
|
||||
} else {
|
||||
glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, previewVao != 0 ? 0 : indices.data());
|
||||
}
|
||||
|
||||
if (previewVao == 0) {
|
||||
glDisableVertexAttribArray(previewProgram->a_position);
|
||||
}
|
||||
|
||||
primaryWindow->End();
|
||||
}
|
||||
|
||||
if (vbuf != 0) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GPUDebugVertex), vertices.data(), GL_STREAM_DRAW);
|
||||
if (which & 2) {
|
||||
secondWindow->Begin();
|
||||
secondWindow->GetContentSize(x, y, fw, fh);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
// The surface is upside down, so vertical offsets are flipped.
|
||||
glViewport((GLint)x, (GLint)-(y + fh - secondWindow->Height()), (GLsizei)fw, (GLsizei)fh);
|
||||
glScissor((GLint)x, (GLint)-(y + fh - secondWindow->Height()), (GLsizei)fw, (GLsizei)fh);
|
||||
BindPreviewProgram(texPreviewProgram);
|
||||
|
||||
if (texPreviewVao == 0 && gl_extensions.ARB_vertex_array_object) {
|
||||
glGenVertexArrays(1, &texPreviewVao);
|
||||
glBindVertexArray(texPreviewVao);
|
||||
glEnableVertexAttribArray(texPreviewProgram->a_position);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
|
||||
|
||||
glVertexAttribPointer(texPreviewProgram->a_position, 2, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), 0);
|
||||
}
|
||||
|
||||
// TODO: For some reason we have to re-upload the data?
|
||||
if (vbuf != 0) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GPUDebugVertex), vertices.data(), GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
if (ibuf != 0 && !indices.empty()) {
|
||||
glBindVertexArray(texPreviewVao);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(u16), indices.data(), GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
Matrix4x4 ortho;
|
||||
ortho.setOrtho(0.0f - (float)gstate_c.curTextureXOffset * invRealTexWidth, 1.0f - (float)gstate_c.curTextureXOffset * invRealTexWidth, 1.0f - (float)gstate_c.curTextureYOffset * invRealTexHeight, 0.0f - (float)gstate_c.curTextureYOffset * invRealTexHeight, -1.0f, 1.0f);
|
||||
glUniformMatrix4fv(texPreviewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr());
|
||||
if (texPreviewVao != 0) {
|
||||
glBindVertexArray(texPreviewVao);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
|
||||
glEnableVertexAttribArray(texPreviewProgram->a_position);
|
||||
glVertexAttribPointer(texPreviewProgram->a_position, 2, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), 0);
|
||||
} else {
|
||||
glEnableVertexAttribArray(texPreviewProgram->a_position);
|
||||
glVertexAttribPointer(texPreviewProgram->a_position, 2, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data());
|
||||
}
|
||||
|
||||
if (indices.empty()) {
|
||||
glDrawArrays(glprim[prim], 0, count);
|
||||
} else {
|
||||
glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, texPreviewVao != 0 ? 0 : indices.data());
|
||||
}
|
||||
|
||||
if (texPreviewVao == 0) {
|
||||
glDisableVertexAttribArray(previewProgram->a_position);
|
||||
}
|
||||
|
||||
secondWindow->End();
|
||||
}
|
||||
|
||||
if (ibuf != 0 && !indices.empty()) {
|
||||
glBindVertexArray(previewVao);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(u16), indices.data(), GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
float scale[] = {
|
||||
480.0f / (float)PSP_CoreParameter().renderWidth,
|
||||
272.0f / (float)PSP_CoreParameter().renderHeight,
|
||||
};
|
||||
|
||||
Matrix4x4 ortho;
|
||||
ortho.setOrtho(-(float)gstate_c.curRTOffsetX, (primaryWindow->TexWidth() - (int)gstate_c.curRTOffsetX) * scale[0], primaryWindow->TexHeight() * scale[1], 0, -1, 1);
|
||||
glUniformMatrix4fv(previewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr());
|
||||
if (previewVao != 0) {
|
||||
glBindVertexArray(previewVao);
|
||||
} else {
|
||||
glEnableVertexAttribArray(previewProgram->a_position);
|
||||
glVertexAttribPointer(previewProgram->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data() + 2);
|
||||
}
|
||||
|
||||
if (indices.empty()) {
|
||||
glDrawArrays(glprim[prim], 0, count);
|
||||
} else {
|
||||
glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, previewVao != 0 ? 0 : indices.data());
|
||||
}
|
||||
|
||||
if (previewVao == 0) {
|
||||
glDisableVertexAttribArray(previewProgram->a_position);
|
||||
}
|
||||
|
||||
primaryWindow->End();
|
||||
|
||||
secondWindow->Begin();
|
||||
secondWindow->GetContentSize(x, y, fw, fh);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glViewport((GLint)x, (GLint)y, (GLsizei)fw, (GLsizei)fh);
|
||||
glScissor((GLint)x, (GLint)y, (GLsizei)fw, (GLsizei)fh);
|
||||
BindPreviewProgram(texPreviewProgram);
|
||||
|
||||
if (texPreviewVao == 0 && gl_extensions.ARB_vertex_array_object) {
|
||||
glGenVertexArrays(1, &texPreviewVao);
|
||||
glBindVertexArray(texPreviewVao);
|
||||
glEnableVertexAttribArray(texPreviewProgram->a_position);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
|
||||
|
||||
glVertexAttribPointer(texPreviewProgram->a_position, 2, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), 0);
|
||||
}
|
||||
|
||||
// TODO: For some reason we have to re-upload the data?
|
||||
if (vbuf != 0) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GPUDebugVertex), vertices.data(), GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
if (ibuf != 0 && !indices.empty()) {
|
||||
glBindVertexArray(texPreviewVao);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(u16), indices.data(), GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
ortho.setOrtho(0.0f - (float)gstate_c.curTextureXOffset * invTexWidth, 1.0f - (float)gstate_c.curTextureXOffset * invTexWidth, 1.0f - (float)gstate_c.curTextureYOffset * invTexHeight, 0.0f - (float)gstate_c.curTextureYOffset * invTexHeight, -1.0f, 1.0f);
|
||||
glUniformMatrix4fv(texPreviewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr());
|
||||
if (texPreviewVao != 0) {
|
||||
glBindVertexArray(texPreviewVao);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
|
||||
glEnableVertexAttribArray(texPreviewProgram->a_position);
|
||||
glVertexAttribPointer(texPreviewProgram->a_position, 2, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), 0);
|
||||
} else {
|
||||
glEnableVertexAttribArray(texPreviewProgram->a_position);
|
||||
glVertexAttribPointer(texPreviewProgram->a_position, 2, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data());
|
||||
}
|
||||
|
||||
if (indices.empty()) {
|
||||
glDrawArrays(glprim[prim], 0, count);
|
||||
} else {
|
||||
glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, texPreviewVao != 0 ? 0 : indices.data());
|
||||
}
|
||||
|
||||
if (texPreviewVao == 0) {
|
||||
glDisableVertexAttribArray(previewProgram->a_position);
|
||||
}
|
||||
|
||||
secondWindow->End();
|
||||
}
|
||||
|
||||
void CGEDebugger::CleanupPrimPreview() {
|
||||
@@ -337,3 +372,14 @@ void CGEDebugger::CleanupPrimPreview() {
|
||||
glsl_destroy(texPreviewProgram);
|
||||
}
|
||||
}
|
||||
|
||||
void CGEDebugger::HandleRedraw(int which) {
|
||||
if (updating_) {
|
||||
return;
|
||||
}
|
||||
|
||||
u32 op = PrimPreviewOp();
|
||||
if (op) {
|
||||
UpdatePrimPreview(op, which);
|
||||
}
|
||||
}
|
||||
@@ -657,6 +657,7 @@ BEGIN
|
||||
POPUP "gepreviewoptions"
|
||||
BEGIN
|
||||
MENUITEM "Export Image...", ID_GEDBG_EXPORT_IMAGE
|
||||
MENUITEM "Show Prim Preview" ID_GEDBG_ENABLE_PREVIEW
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
+2
-1
@@ -335,6 +335,7 @@
|
||||
#define ID_HELP_GITHUB 40168
|
||||
#define IDC_GEDBG_RECORD 40169
|
||||
#define ID_GEDBG_EXPORT_IMAGE 40170
|
||||
#define ID_GEDBG_ENABLE_PREVIEW 40171
|
||||
#define ID_SIMPLEUI_TOGGLE 40200
|
||||
#define ID_SIMPLEUI_HIDE 40201
|
||||
|
||||
@@ -349,7 +350,7 @@
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 256
|
||||
#define _APS_NEXT_COMMAND_VALUE 40171
|
||||
#define _APS_NEXT_COMMAND_VALUE 40172
|
||||
#define _APS_NEXT_CONTROL_VALUE 1200
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
|
||||
Reference in new issue
Block a user