I have a D3D11 application for Windows Store that currently does not use antialiasing, and I would like to enable it.
According to MSDN, MSAA is disabled in Windows Store apps:
DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
Use this flag to specify the flip presentation model and to specify that DXGI persist the contents of the back buffer after you call IDXGISwapChain1::Present1. This flag cannot be used with multisampling.
Note Windows Store apps must use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL.
Because this limitation applies only to the back buffer, it sounds like the best workaround is to create a new off-screen render target, enable MSAA on that, render everything to it, and immediately before Present, blit the off-screen target to the back buffer (probably with ResolveSubresource).
I've started implementing this, but I'm not sure how to modify my swap chain and render target view. Can anybody advise me as to the correct order of operations here?
What you suggest is correct. Create an MSAA render target using CreateTexture2D followed by CreateRenderTargetView. The DXGI_SAMPLE_DESC field of D3D11_TEXTURE2D_DESC contains the MSAA settings. Then render your scene to this render target, and ResolveSubresource into the back buffer. The swap chain doesn't need to change.
Related
I want make a Direct2D GUI that will run on a DLL and will render with the Direct3D of the application that I inject into it.
I know that I can simply use ID2D1Factory::CreateDxgiSurfaceRenderTarget to make a DXGI surface and use it as d2d render target, but this require enabling the flag D3D11_CREATE_DEVICE_BGRA_SUPPORT on Direct3D's device.
The problem is that the application creates its device without enabling this flag and, for this reason, ID2D1Factory::CreateDxgiSurfaceRenderTarget fails.
I am trying to find a other way to draw on the application window (externally or inside window's render target) that also works if that window is in full-screen.
I tried these alternatives so far:
Create a d2d render target with ID2D1Factory::CreateDCRenderTarget. This worked, but the part I rendered was blinking/flashing (show and hide very fast in loop). I also called ID2D1DCRenderTarget::BindDC before ID2D1RenderTarget::BeginDraw, but it just blinks but a bit less, so I still had the same issue.
Create a new window that will always be on the top of every other window and render there with d2d but, if the application goes into full-screen, then this window does not show on screen.
Create a second D3D device with enabled the D3D11_CREATE_DEVICE_BGRA_SUPPORT flag and share an ID3D11Texture2D resource between the device of the window and my own, but I wasn't able to make it work... There are not a lot of examples on how to do it. The idea was to create a 2nd device, draw with d2d on that device and then sync the 2 D3D devices – I followed this example (with direct11).
Create a D2D device and share the data of d2d device with d3d device; but, when I call ID2D1Factory1::CreateDevice to create the device it fails because the D3D device is created without enabling the D3D11_CREATE_DEVICE_BGRA_SUPPORT flag. I started with this example.
I've heard of hardware overlay but it works only on some graphics cards and I think I will have problems with this https://learn.microsoft.com/el-gr/windows/win32/medfound/hardware-overlay-support.
I am currently at a dead end; I don't know what to do. Does anyone have any idea that may help me?
Maybe is there any way to draw on screen and work even if a window is in full-screen?
The #3 is the correct one. Here’s a few tips.
Don’t use keyed mutexes. Don’t use NT handles. The only flag you need is D3D11_RESOURCE_MISC_SHARED.
To properly synchronize access to the shared texture across devices, use queries. Specifically, you need a query of type D3D11_QUERY_EVENT. The workflow should look like following.
Create a shared texture on one device, open in another one. Doesn’t matter where it’s created and where imported. Don’t forget the D3D11_BIND_RENDER_TARGET flag. Also create a query.
Create D2D device with CreateDxgiSurfaceRenderTarget of the shared texture, render your overlay into the shared texture with D2D and/or DirectWrite.
On the immediate D3D device context with the BGRA flag which you use for D2D rendering, call ID3D11DeviceContext.End once, passing the query. Then wait for the ID3D11DeviceContext.GetData to return S_OK. If you care about electricity/thermals use Sleep(1), or if you prioritize latency, busy wait with _mm_pause() instructions.
Once ID3D11DeviceContext.GetData returned S_OK for that query, the GPU has finished rendering your 2D scene. You can now use that texture on another device to compose into 3D scene.
The way to compose your 2D content into the render target depends on how do you want to draw your 2D content.
If that’s a small opaque quad, you can probably CopySubresourceRegion into the render target texture.
Or, if your 2D content has transparent background, you need a vertex+pixel shaders to render a quad (4 vertices) textured with your shared texture. BTW you don’t necessarily need a vertex/index buffer for that, there’s a well-known trick to do without one. Don’t forget about blend state (you probably want alpha blending), depth/stencil state (you probably want to disable depth test when rendering that quad), also the D3D11_BIND_SHADER_RESOURCE flag for the shared texture.
P.S. There’s another way. Make sure your code runs in that process before the process created their Direct3D device. Then use something like minhook to intercept the call to D3D11.dll::D3D11CreateDeviceAndSwapChain, in the intercepted function set that BGRA bit you need then call the original function. Slightly less reliable because there’re multiple ways to create a D3D device, but easier to implement, will work faster, and use less memory.
I want to get the unity context into opengl so I can display a unity render texture in an opengl glfw window. I tried using
oldContext = glfwGetCurrentContext(); but the value of oldContext is just null.
I am trying to use the low-level native unity plugin and Texture.GetNativeTexturePtr
Any help would be greatly appreciated!
OpenGL context cannot be queried like OpenGL state related objects via some glGet* API.Context is not part of OpenGL API,it is a part of the system you're running on and it exists to allow you maintaining of OpenGL state and issue command to the driver. You must access a system specific handle that points to the context via system specific API.On Windows (WinGDI)that's would be
HGLRC wglGetCurrentContext();
On linux see related GLX API. You need to find functions to access GLXContext
I did it once in Unity3D (framebuffer readout plugin). But it used Unity's OpenGL or DirectX context to issue API commands only.
Also,I am not sure you can 'inject' or share a context for a window that doesn't own that context. You see, when you (or Unity) init display it creates context and related GL resources,like the default FBO with all required attachments on its own,and that FBO is mapped to some system resource(device) which takes actually care of presenting those pixels on the screen. Therefore, I am not sure display context can be moved from Window to Window in the same manner that a context can be shared between threads.(But I can be wrong on this one)
You can create your plugin Window on some thread,with its own GL context. Then create and share a texture object between those two. Remember, GL textures are shareable. If you copy contents from Unity's screen FBO into that texture,then you can copy it into your plugin's screen FBO from that texture as well.
Btw,look at this SO question .You can see there vendor specific GL extensions which allow copying data into texture from different contexts without requiring shared context,share lists setup.
Regarding why GLFW returns you nullptr. In your example you use GLFW library.
glfwGetCurrentContext()
But if you look at the source code,you see this:
GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return _glfwPlatformGetTls(&_glfw.contextSlot);
}
Which probably means that it retrieves a pointer to GLFWWindow from its own cache and not from the system.And if you didn't create that context via GLFW,you won't get any valid pointer. So try working directly with your system related API as explained above.
I'm looking to create a child frame (CWnd subclass) that has transparent regions.
However, I can't seem to get the transparency part working. From what I understand, I would need to enable transparency when creating the ID2D1HwndRenderTarget using the D2D1_ALPHA_MODE_IGNOREflag (as seen here) However, I don't create the render target that way. Instead, I use EnableD2DSupport() in my OnCreate() method. When I try to clear the render target with CHwndRenderTarget::Clear(ColorF) using a color with opacity set to 0.0, the opacity is ignored. I do this in my function handling the AFX_WM_DRAW2D message, with the render target taken from the LPARAM.
Any ideas on how to get transparency working for this?
D2D1_ALPHA_MODE_IGNORE means what it says - the alpha channel is ignored (the drawings are always opaque). The SO question, you've linked targets the opposite problem, when the drawings are always transparent.
As I see, the EnableD2DSupport() creates an ID2D1HwndRenderTarget, but most probably with a D2D1_ALPHA_MODE_IGNORE flag. You need D2D1_ALPHA_MODE_PREMULTIPLIED or D2D1_ALPHA_MODE_STRAIGHT, so you can use the alpha channel.
If possible, create a ID2D1HwndRenderTarget manually with the proper alpha mode and then attach it to the CHwndRenderTarget with CHwndRenderTarget::Attach
Another way (which I would have chosen) is the Direct2D 1.1 way (more precise - ID2D1DeviceContext), managing the whole drawing process manually. For some guidances look at this answer.
I want to render a scene and display it on the monitor, while rendering another one to a texture.
Do I need to create two swapchains? How do I create the second swapchain in this case? I tried to call CreateSwapChainForCoreWindow but got memory access exceptions.
Swapchains are really just for displaying stuff.
To render to something, you have to add a render target view to the device via the OMSetRenderTargets() call. You can create render target views via CreateRenderTargetView(), which takes a resource as input. Textures are resources too... you just have to create them with the D3D11_BIND_RENDER_TARGET flag.
That's just a few cues that should be able to point you into the right direction.
Btw, Swapchains have buffers, which are resources that are used to create a render target view as well. That's how you render to a swapchain; it really doesn't have anything to do with "swapchains" at all.
I need to develop an app using Java wrapper for OpenGL LWJGL.The app will run on remote server in a headless mode.I am trying to understand if and how is it possible taking into consideration the fact that GL context in LWJGL (and in other APis) is created via Java UI elements like Canvas etc.In my case I need to be able to init GL context without creating a window as the drawing targets will be FBOs from which the pixel buffers will render to texture. There is one possible solution though already called PBuffer (I guess pixel buffer) object in LWJGL.It indeed doesn't need GL context created via window as it creates it internally.I don't want to use this method both because it is older concept (and weaker ) than Frame buffer object and because I am using OGL 3.3 -> .So I really don't want to mix with any old pipeline legacy.
I have basically 2 questions:
1.Can I create a context without setting up a window to use for FBO based rendering(headless mode) ?
2.If the answer to the first question is negative ,then can I run on the remote server such an app where the windows is still initialized for the sake of context access ?
UPDATE:
The question can be closed.I tested it via first initialization done with PBuffers to set a context.Then FBO rendering works as supposed.
I found the answer on my own. One should set PBuffer first to create headless GL context. Once it is created we can use FBOs to render frames into images.