Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Vulkan drawable size for frame buffer scale when using SDL and Vulkan #3190

Closed
wants to merge 1 commit into from
Closed

Use Vulkan drawable size for frame buffer scale when using SDL and Vulkan #3190

wants to merge 1 commit into from

Conversation

andystanton
Copy link

@andystanton andystanton commented May 3, 2020

Problem

When running the Vulkan SDL example I noticed that the display can be scaled incorrectly. This occurs when the example is launched on a non-retina monitor that is used with a retina Macbook. It doesn't just look incorrect - the cursor behaves as though the display has been scaled correctly, making mouse input unusable.

The first screenshot shows the expected behaviour with the SDL + OpenGL3 example, and the second shows the issue with the SDL + Vulkan example:

SDL + OpenGL3

Screenshot 2020-05-03 at 21 13 07

SDL + Vulkan

Screenshot 2020-05-03 at 21 13 18

In examples/imgui_impl_sdl.cpp The code to determine the framebuffer scale looks like this:

int w, h;
int display_w, display_h;
SDL_GetWindowSize(window, &w, &h);
SDL_GL_GetDrawableSize(window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)w, (float)h);
if (w > 0 && h > 0)
    io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);

The code always uses SDL_GL_GetDrawableSize but when using Vulkan, SDL_Vulkan_GetDrawableSize[1] should be used instead.

Solution

The correct SDL_*_GetDrawableSize function can be determined by inspecting whether the window has the Vulkan flag set. If it doesn't, the original behaviour is used:

if (SDL_GetWindowFlags(window) & SDL_WINDOW_VULKAN)
    SDL_Vulkan_GetDrawableSize(window, &display_w, &display_h);
else
    SDL_GL_GetDrawableSize(window, &display_w, &display_h);

However, SDL_GL_GetDrawableSize comes from SDL_Video.h which is included by default, but SDL_Vulkan_GetDrawableSize comes from SDL_vulkan.h which is not included by default. To prevent bringing a whole new include in, I propose forward declaring the function instead:

extern "C" {
    extern DECLSPEC void SDLCALL SDL_Vulkan_GetDrawableSize(SDL_Window * window, int * w, int * h);
}

Testing

Firstly, I encountered the issue mentioned in #3177 and had to apply the fix from that PR locally.

Then I used the following Makefile from the root of the imgui repo to build the SDL OpenGL and Vulkan examples.

IMGUI_SRC_DIR := .
IMGUI_INCLUDE_DIR := .
SDL2_INCLUDE_DIR := /usr/local/include/SDL2
IMGUI_IMPL_INCLUDE_DIR := ./examples
IMGUI_IMPL_SRC_DIR := ./examples
GL3W_DIR := ./examples/libs/gl3w/GL
GL3W_INCLUDE_DIR := ./examples/libs/gl3w
OUT_GL := imgui-sdl-gl
OUT_VULKAN := imgui-sdl-vulkan

GL3W_CFLAGS := -Wall -I$(GL3W_INCLUDE_DIR)

SDL_IMPL_CFLAGS = -I$(IMGUI_INCLUDE_DIR) -I$(IMGUI_IMPL_INCLUDE_DIR) -I$(SDL2_INCLUDE_DIR)
OPENGL3_IMPL_CFLAGS = -I$(GL3W_INCLUDE_DIR) -I$(IMGUI_INCLUDE_DIR) -I$(IMGUI_IMPL_INCLUDE_DIR) -DIMGUI_IMPL_OPENGL_LOADER_GL3W
VULKAN_IMPL_CFLAGS = -I$(IMGUI_INCLUDE_DIR) -I$(IMGUI_IMPL_INCLUDE_DIR)

GL_CFLAGS := -Wall -I$(IMGUI_INCLUDE_DIR) -I$(IMGUI_IMPL_INCLUDE_DIR) -I$(SDL2_INCLUDE_DIR) -I$(GL3W_INCLUDE_DIR) -g -DIMGUI_IMPL_OPENGL_LOADER_GL3W
GL_LFLAGS := -lSDL2 -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo -lc++ -lvulkan

VULKAN_CFLAGS := -Wall -I$(IMGUI_INCLUDE_DIR) -I$(IMGUI_IMPL_INCLUDE_DIR) -I$(SDL2_INCLUDE_DIR) -g
VULKAN_LFLAGS := -lSDL2 -framework Cocoa -framework IOKit -framework CoreVideo -lc++ -lvulkan -lMoltenVK

OBJS_IMGUI = \
	imgui.o	\
	imgui_demo.o \
	imgui_draw.o \
	imgui_widgets.o \

OBJS_SDL = imgui_impl_sdl.o

OBJS_GL = \
	imgui_impl_opengl3.o \
	gl3w.o \
	main-gl.o \
	main-gl

OBJS_VULKAN = \
	imgui_impl_vulkan.o \
	main-vulkan.o \
	main-vulkan

.PHONY: all clean

all: $(OBJS_IMGUI) $(OBJS_SDL) $(OBJS_GL) $(OBJS_VULKAN)

main-gl: main-gl.o imgui.o imgui_demo.o imgui_draw.o imgui_widgets.o gl3w.o imgui_impl_sdl.o imgui_impl_opengl3.o
	$(CXX) \
		$(IMGUI_SRC_DIR)/main-gl.o \
		$(IMGUI_IMPL_SRC_DIR)/imgui_impl_sdl.o \
		$(IMGUI_IMPL_SRC_DIR)/imgui_impl_opengl3.o \
		$(GL3W_DIR)/gl3w.o \
		$(IMGUI_SRC_DIR)/imgui.o \
		$(IMGUI_SRC_DIR)/imgui_demo.o \
		$(IMGUI_SRC_DIR)/imgui_draw.o \
		$(IMGUI_SRC_DIR)/imgui_widgets.o \
		-o $(OUT_GL) $(GL_LFLAGS)

main-vulkan: main-vulkan.o imgui.o imgui_demo.o imgui_draw.o imgui_widgets.o imgui_impl_sdl.o imgui_impl_vulkan.o
	$(CXX) \
		$(IMGUI_SRC_DIR)/main-vulkan.o \
		$(IMGUI_IMPL_SRC_DIR)/imgui_impl_sdl.o \
		$(IMGUI_IMPL_SRC_DIR)/imgui_impl_vulkan.o \
		$(IMGUI_SRC_DIR)/imgui.o \
		$(IMGUI_SRC_DIR)/imgui_demo.o \
		$(IMGUI_SRC_DIR)/imgui_draw.o \
		$(IMGUI_SRC_DIR)/imgui_widgets.o \
		-o $(OUT_VULKAN) $(VULKAN_LFLAGS)

imgui_impl_sdl.o: $(IMGUI_IMPL_SRC_DIR)/imgui_impl_sdl.cpp $(IMGUI_IMPL_SRC_DIR)/imgui_impl_sdl.h
	$(CXX) $(SDL_IMPL_CFLAGS) -c $< -o $(IMGUI_IMPL_SRC_DIR)/$@

imgui_impl_opengl3.o: $(IMGUI_IMPL_SRC_DIR)/imgui_impl_opengl3.cpp $(IMGUI_IMPL_SRC_DIR)/imgui_impl_opengl3.h
	$(CXX) $(OPENGL3_IMPL_CFLAGS) -c $< -o $(IMGUI_IMPL_SRC_DIR)/$@

imgui_impl_vulkan.o: $(IMGUI_IMPL_SRC_DIR)/imgui_impl_vulkan.cpp $(IMGUI_IMPL_SRC_DIR)/imgui_impl_vulkan.h
	$(CXX) $(VULKAN_IMPL_CFLAGS) -c $< -o $(IMGUI_IMPL_SRC_DIR)/$@

gl3w.o: $(GL3W_DIR)/gl3w.c $(GL3W_DIR)/gl3w.h $(GL3W_DIR)/glcorearb.h
	$(CC) $(GL_CFLAGS) -c $< -o $(GL3W_DIR)/$@

main-gl.o: $(IMGUI_IMPL_SRC_DIR)/example_sdl_opengl3/main.cpp
	$(CXX) $(GL_CFLAGS) -c $< -o $(IMGUI_SRC_DIR)/$@

main-vulkan.o: $(IMGUI_IMPL_SRC_DIR)/example_sdl_vulkan/main.cpp
	$(CXX) $(VULKAN_CFLAGS) -c $< -o $(IMGUI_SRC_DIR)/$@

clean:
	rm -f $(IMGUI_SRC_DIR)/*.o
	rm -f $(IMGUI_IMPL_SRC_DIR)/*.o
	rm -f $(GL3W_DIR)/*.o
	rm -f $(OUT_GL)
	rm -f $(OUT_VULKAN)

Before applying the fix, this resulted in the screenshots above when launching the example code on a non-retina monitor that is attached to a retina Macbook. After applying the fix, the behaviour for the Vulkan example aligned with the OpenGL one as expected.

The issue is not present when running the examples on just a retina Macbook, or with a retina display attached to a retina Macbook.

References

[1] libsdl.org/SDL_Vulkan_GetDrawableSize

@ocornut
Copy link
Owner

ocornut commented Jul 13, 2020

Hello @andystanton,

Sorry for the lack of earlier answer. Any reason for closing this?

This seems still useful, we're currently looking at variety of DPI related changes which will likely be addressed together.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants