Closed QuantumDeveloper closed 9 years ago
Could you fix the gist link? It takes me to a blank webpage.
I had a problem similar to that one in a Windows Phone Silverlight 8.1 app and managed to solve it, but without you specific case I can't help you further.
Sorry, something strange with that gists. https://gist.github.com/QuantumDeveloper/469db5ea0270d4524d38
I found out that presenter instance in d2dservice is locking resizing and if I delete if, it would resize, but in that case I need to recreate my presenter each time and it will cause outofmemory exception....
@r2d2rigo do you have any ideas, or you didn`t look yet?
@QuantumDeveloper Yes, I have taken a look at it and have some suggestions:
SwapChainGraphicsPresenter
in your Direct2D service. Instead, use the one already created inside GraphicsDevice.GraphicsDeviceManager
instead of the GraphicsDevice
to the constructor of the D2D service. Then, subscribe to the GraphicsDeviceBegin
event for destroying your D2D resources and GraphicsDeviceEnd
for recreating, since resizing the SwapChainPanel
seems to be resetting the device.Check thoroughly that you are disposing everything that you are creating.
Everything you mean even d2d device with context and resources (brushes and other?)
That was just a guideline for preventing leaks, as in my experience leaking memory with SharpDX is quite easy.
I don't know if you will need to dispose the D2D device/context too, but if releasing the brushes and images isn't enough try doing it too.
I tried to delete everything - it works partly (begin resizing), but still present messages about resizing error and it still crashes because of memory with message:
First-chance exception at 0x76E01D4D in App6.exe: Microsoft C++ exception: _com_error at memory location 0x062AC34C.
Here is the link to my updated project https://gist.github.com/QuantumDeveloper/7f3535ea316a73d4cc6f
I had no luck trying to preserver the D2D device/context, so I have commented your first gist with a version that destroys all D2D resources when the device starts changing and recreates them when it ends. Hope this works for you.
@r2d2rigo Thanks for hint. I tried to do this - _disposeCollector.DisposeAndClear();
and that works - no memory exceptions anymore! (At last). But I have questions regarding memory leaks:
when I should use ToDispose() and ToDIsposeContent()? Or just use disposecollector class instead all of them? I didn`t find answer on this questions anywhere, so maybe you know something about this aspect of sharpdx?
ToDispose
and ToDisposeContent
should be used for objects instantiated inside your Game
class. The difference is that ToDispose
is called when the Game
class is being disposed, while the ToDisposeContent
is called when UnloadContent
happens.
For non-Game
classes, use the DisposeCollector
and add the created objects there.
OK, now I understood it better. Thanks a lot for help!!!!
@QuantumDeveloper are you targetting Windows 8.1 exclusively by any chance?
@r2d2rigo I think yes, because I am sick from old platfom limitations (WinAPI, WinForms, WPF). I hope that Windows 9 will improve that was done in 8.1, make modernUI run in window and some other improvements, but for now I am happy with that WIn 8.1 gives.
@QuantumDeveloper Oh, just remembered that you are using SharpDX.Toolkit, so what I was thinking about won't work in your case :(
I was going to suggest that if you are creating your SwapChain from scratch, you could try settings its SourceSize
instead of resizing it with the new APIs added in DirectX 11.2: http://msdn.microsoft.com/en-us/library/windows/desktop/dn280408(v=vs.85).aspx
@r2d2rigo I am using toolkit, so it created automatically. But anyway, thanks for hint
@r2d2rigo Could I ask you about help one more time? Now its about render to texture instead of backbuffer and copy result to back buffer
Yes, of course. You have a repro project/code?
-----Original Message----- From: "QuantumDeveloper" notifications@github.com Sent: 07/09/2014 15:14 To: "r2d2rigo/MyFirstDirect2D" MyFirstDirect2D@noreply.github.com Cc: "Rodrigo Diaz" r2d2rigo@gmail.com Subject: Re: [MyFirstDirect2D] [SharpDX] D2D + D3DPresenter.Resize(...)exception (#1)
@r2d2rigo Could I ask you about help one more time? Now its about render to texture instead of backbuffer and copy result to back buffer — Reply to this email directly or view it on GitHub.=
Sure. I already created my depth buffer and rendertarget view (I want to enable MSAA in WinRT) but the problem is in rendering part. I am not sure how to correctly render to texture and then copy to backbuffer. My original project is quite big, so i will make simple test project.
Here is the link to my one drive storage: https://onedrive.live.com/?cid=650F345C1F75A314&id=650F345C1F75A314!105 project named App8. I made as simple as possible. Method "SetCustomRenderTarget()" create multisampled depthbuffer and rendertargetview with texture.
Now I draw to backbuffer directly, but I wish to render to my texture and then copy it to backbuffer. I comment non working code in Draw() method.
@r2d2rigo Did you try my demo app?
Sorry for the delay, my current PC isn't DX11 compatible and had to make some minor changes to your projects. I have tested the following code and it works for rendering to a separate render target:
if (_modelLoaded)
{
Texture2D rtTex = Texture2D.New(GraphicsDevice, new Texture2DDescription()
{
Width = 100,
Height = 100,
Format = Format.R8G8B8A8_UNorm,
BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
SampleDescription = new SampleDescription(1,0),
Usage = ResourceUsage.Default,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.None,
ArraySize = 1,
MipLevels = 1,
});
RenderTarget2D rt = RenderTarget2D.New(GraphicsDevice, (SharpDX.Direct3D11.Texture2D)rtTex);
DepthStencilView oldDepth;
RenderTargetView[] oldTargets = GraphicsDevice.GetRenderTargets(out oldDepth);
GraphicsDevice.SetRenderTargets(rt);
GraphicsDevice.Clear(Color.CornflowerBlue);
GraphicsDevice.SetVertexBuffer(vertices);
GraphicsDevice.SetIndexBuffer(indices, true);
GraphicsDevice.SetVertexInputLayout(inputLayout);
customEffect.CurrentTechnique.Passes["Pass0"].Apply();
GraphicsDevice.DrawIndexed(PrimitiveType.TriangleList, indices.ElementCount);
GraphicsDevice.SetRenderTargets(oldDepth, oldTargets);
spriteBatch.Begin();
spriteBatch.Draw(rtTex, new RectangleF(0, 0, 300, 300), Color.White);
spriteBatch.End();
}
base.Draw(gameTime);
}
Thanks a lot, but I have a few questions:
SampleDescription
values when creating
the texture for the render target. And in the sample I didn't use a depth
buffer, so if you create it, make sure it has the same SampleDescription
values than the render target.LoadContent
.Thanks. And what about my last question?
Well, it depends. If you use the SpriteBatch
approach for drawing the render target, you have to keep switching them. However, browsing the MSDN docs, if you use ResolveSubresource
(http://msdn.microsoft.com/en-us/library/windows/apps/dn458384.aspx) for copying the contents of the render target to the back buffer, you don't have to do it:
GraphicsDevice.DrawIndexed(PrimitiveType.TriangleList, indices.ElementCount);
((SharpDX.Direct3D11.DeviceContext)GraphicsDevice).ResolveSubresource(rt, 0, GraphicsDevice.BackBuffer, 0, Format.R8G8B8A8_UNorm);
Thnaks a lot for your help. I will test it at home and write the result here.
@r2d2rigo One small addidtion and small question: You must set also Depthstencilbuffer to avoid troubles with z-buffer as I found out.
And now I cant get work my D2D. I send it created rendertarget2d, but it don`t render to it anything.
In output window I see the following error:
D3D11 ERROR: ID3D11DeviceContext::ResolveSubresource: The formats of each Resource are not compatible each other. Source Resource format is (0x1c, R8G8B8A8_UNORM). Destination Resource format is (0x57, B8G8R8A8_UNORM). [ RESOURCE_MANIPULATION ERROR #292: DEVICE_RESOLVESUBRESOURCE_SOURCE_INVALID]
Maybe this is the reason? But I can`t understand why it is so? I rendered text to simple texture and it displays on backbuffer. What I am missing?
Take a look at the error message: your backbuffer is in BGRA format so it works with Direct2D, but the rendertarget I created in the sample code is RGBA. Since the color formats don't match, it is failing.
Change the format of the off-screen render target to BGRA and it should work.
@r2d2rigo Already tried:
rendertoTextureDescription.Format = Format.B8G8R8A8_UNorm;
...
device.ResolveSubresource(rt, 0, GraphicsDevice.BackBuffer, 0, Format.B8G8R8A8_UNorm);
Message: D3D11 ERROR: ID3D11DeviceContext::ResolveSubresource: The formats of each Resource are not compatible each other. Source Resource format is (0x57, B8G8R8A8_UNORM). Destination Resource format is (0x1c, R8G8B8A8_UNORM). [ RESOURCE_MANIPULATION ERROR #292: DEVICE_RESOLVESUBRESOURCE_SOURCE_INVALID]
Interesting detail I see the first frame with text and on second fram It begins to show this message. Maybe resizing do something with it?
Yes, apparently the second time PreparingDeviceSettings
is called, it ignores to set the back buffer to BGRA based solely on e.GraphicsDeviceInformation.DeviceCreationFlags = DeviceCreationFlags.BgraSupport
. You can fix it by specifying the pixel format by yourself there: graphicsDeviceManager.PreferredBackBufferFormat = PixelFormat.B8G8R8A8.UNorm;
.
You will laugh, but I solved this problem:
Texture format must be this:
rendertoTextureDescription.Format = Format.R8G8B8A8_UNorm;
but resolvesubresorce must be this:
device.ResolveSubresource(rt, 0, GraphicsDevice.BackBuffer, 0, GraphicsDevice.BackBuffer.Format);
And now its working.
But I have one more question regarding to apllying texture only to the part of back buffer. For ex, for displaying minimap. I have texture with 200*150 px and I want to place it in the bottom corner of the screen. I found method device.CopySubresourceRegion(); but It not working with multisampled texture.
I'm afraid you will need to resort to draw the texture over everything with an orthographic projection for that. SpriteBatch
should do the trick.
its working for me, but... always but
Does sprite butch support multisampling? Because when I render with spritebatch without updatesubresource - texture was completely without multisampling
What size is the texture you are drawing on the down right part of the screen? Because if it is bigger than the size in pixels of the area you are drawing to, it will be downscaled and you will lose the quality introduced by multisampling.
Texture is 1920*1080 and I tested it by applying to back buffer. ANd I see that quality is awful, but with subresource the same texture is drawing perfect.
BTW, do you know something about next WinRT version? Will it swapchin support multisampling from the box? I hope so, because now its not very comfortable to render that way. At least it will be a little easy to handle drawing ro backbuffer if not rendering to texture.
I think you have two options:
SpriteBatch
.ResolveSubresource
on it with the drawing pipeline you already have, and draw the texture of the new target with SpriteBatch
.No, I don't know much about what's coming next, specially with all the changes that Threshold will supposedly have.
By the way, why don't you try using any of the shader-based antialiasing techniques?
I also want to try that techiques, but I dont know mush about shaders, so for now I am using very-very basic shaders. Shaders itself its black spot for me yet. I begin to understand them, but many things I don`t understand for now.
And about spritebatch - does it has good performance? I tried to make simple 2d particle and see that if I generate more than 500 small particles at onle, by FPS descend to 30 or lower. It is very interesting, because using particle with shaders and D3D I can generate at least 50 000 particle without performance loss.
AFAIK Toolkit's SpriteBatch is adapted from the one in DirectXTK, so it should perform similarly to XNA. Maybe you have more texture/state changes? Looking at it with a profiler would show what is making it go so slow.
OK, I will do that to be sure what I am doing wrong, But it seems that with shaders and D3D I can do more effecient particles system anyway. More that 10000 particles with spritebatch I couldnt do in any case.
@r2d2rigo Hello again) May I disturb you a little?
Mentioning yesterday issues. I found that using spritebatch I receive the following error: D3D11 ERROR: ID3D11DeviceContext::DrawIndexed: The Shader Resource View dimension declared in the shader code (TEXTURE2D) does not match the view type bound to slot 0 of the Pixel Shader unit (TEXTURE2DMS). This mismatch is invalid if the shader actually uses the view (e.g. it is not skipped due to shader code branching). [ EXECUTION ERROR #354: DEVICE_DRAW_VIEW_DIMENSION_MISMATCH]
As I understand this happens because I use in shader Texture2d instead Texture2DMS, but if I not use spritebatch, there is no such error. So, maybe I am doing something wrong with spritebatch? (Interesting that in the same time it displays texture correct)
Here is how I am using spritebatch class
d2DService.Context.BeginDraw();
d2DService.Context.DrawText(D2DText, d2DService.TextFormat, d2DService.RectangleF,
d2DService.TextBrush);
d2DService.Context.EndDraw();
device.ResolveSubresource(rt, 0, GraphicsDevice.BackBuffer, 0, GraphicsDevice.BackBuffer.Format);
GraphicsDevice.SetRenderTargets(oldDepth, oldTargets);
basic.CurrentTechnique.Passes[0].Apply();
spriteBatch.Begin();
spriteBatch.Draw(rt, new RectangleF((int)SwapChainPanel.ActualWidth - 500, (int)SwapChainPanel.ActualHeight - 350, 500, 350), Color.White);
spriteBatch.End();
DId you faced with such issue?
You are trying to draw a multisampled texture while the code for the shader only supports standard 2D textures. You will have to draw a non-multisampled texture or roll your own SpriteBatch
shader that fixes it.
I am trying to find some sample code to find out how to use MS texture in pixel shader, but for now I coudnt. As I understand I need only pixel shader, but what I must calculate in it? Everything already calculated... Or I can create new technique and define new pixel shader with texture2DMS, but still cant understand how to work with that texture in shader.
Simple texture is:
float4 LightPixelShader(PixelInputType input) : SV_TARGET
{
float4 textureColor;
float3 lightDir = 0;
float lightIntensity;
float4 color;
// Sample the pixel color from the texture using the sampler at this texture coordinate location.
textureColor = shaderTexture.Sample(sampleType, input.tex);
// Invert the light direction for calculations.
color = AmbientColor * AmbientIntensity;
// Calculate the amount of light on this pixel.
lightIntensity = saturate(dot(input.normal, lightDirection));
// Determine the final amount of diffuse color based on the diffuse color combined with the light intensity.
color = saturate(diffuseColor * lightIntensity);
// Multiply the texture pixel and the final diffuse color to get the final pixel color result.
color = color + textureColor;
return color;
}
With MS texture I need do something like?
float4 LightPixelShader(PixelInputType input) : SV_TARGET
{
float4 textureColor;
float3 lightDir = 0;
float lightIntensity;
float4 color;
MScount = 4;
for (int i = 0; i < MScount; i++)
{
//what here?
}
return color;
}
You can copy the one provided by the Toolkit: https://github.com/sharpdx/SharpDX/blob/master/Source/Toolkit/SharpDX.Toolkit.Graphics/StockEffects/HLSL/SpriteEffect.fx
Copy and paste the definitions used from Macros.fxh and change all Texture2D
types to Texture2DMS
. You don't have to sample manually the neighbouring pixels, the Sample
instruction will do it for you.
I feel myself like a complete idiot. I cant understand what is happening there. Need I vertex shader or not? Here I found sample from hierogliph engine, but still not completely understand it. https://searchcode.com/codesearch/view/10329980/
When I use it after rendering I thinhk I dont need vertex shader at all, but in that case what I must write in pixel shader. I just don`t know...
@r2d2rigo Did you not tired to help me yet? Hehe)
@QuantumDeveloper Sure not! :) Did you solve the shader problem?
Yes. I solved it with additional render target. I resolve my texture to 2 subresources and then its render without errors. For I now I don`t understand how to work correctly with multisampled texture, so I leave it as is and start working with skybox.
For the current moment skybox is load and displays correctly, but I have one issue - faces disappearing when camera look on them from some angle.
Like in the picture below.
This was caused by logarithmic buffer in shader code. Here is the skybox effect sample:
matrix worldMatrix;
matrix viewMatrix;
matrix projectionMatrix;
float3 CameraPosition;
float zNear;
float zFar;
TextureCube skyboxTexture;
SamplerState skyBoxSampler;
struct VertexShaderInput
{
float4 Position : SV_POSITION0;
};
struct VertexShaderOutput
{
float4 Position : SV_POSITION0;
float3 TextureCoordinate : TEXCOORD0;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
float4 worldPosition = mul(input.Position, worldMatrix);
float4 viewPosition = mul(worldPosition, viewMatrix);
output.Position = mul(viewPosition, projectionMatrix);
//this line caused that error
output.Position.z = log(zNear*output.Position.z + 1) / log(zNear*zFar + 1) * output.Position.w;
float4 VertexPosition = mul(input.Position, worldMatrix);
output.TextureCoordinate = VertexPosition - CameraPosition;
return output;
}
float4 PixelShaderFunction(VertexShaderOutput input) : SV_TARGET
{
return skyboxTexture.Sample(skyBoxSampler, input.TextureCoordinate);
}
technique Skybox
{
pass Pass0
{
Profile = 11.0;
VertexShader = VertexShaderFunction;
PixelShader = PixelShaderFunction;
}
}
Problem is that if I remove that line and far away from some object - skybox cube began flickering. Logarithmic depth buffer solved that issue, but caused side effect described above. Is there any way to solve this issue?
How are you drawing the skybox? You should draw it with z-read only so no depth artifacts show.
I render like this:
GraphicsDevice.SetRenderTargets(depthStencilBuffer, rt);
GraphicsDevice.Clear(Color.CornflowerBlue);
skyboxEffect.Techniques["Skybox"].Passes[0].Apply();
GraphicsDevice.SetRasterizerState(GraphicsDevice.RasterizerStates.CullNone);
GraphicsDevice.SetDepthStencilState(GraphicsDevice.DepthStencilStates.DepthRead);
primitive.Draw();
GraphicsDevice.SetDepthStencilState(GraphicsDevice.DepthStencilStates.Default);
customEffect.CurrentTechnique.Passes[0].Apply();
And it works... but without my logarothmic z-buffer. So, I cannot do it infinit size.....
Hello. I don`t know would you be so kind to help me understand this issue, but I ask for your help.
I faced with issue that when I use D2D on D3D backbuffer and resize swapchainpanel, resizing fails because it always says DXGI ERROR: IDXGISwapChain::ResizeBuffers: Swapchain cannot be resized unless all outstanding buffer references have been released. [ MISCELLANEOUS ERROR #19: ]
But only resource I am using is D2D render target and I dispose it on begin device change event, but inside GraphicsDevice itself during resizing it just crashes on Resize() method. If I don
t use D2D, resizing goes well, so I think this is definately because of D2D, but I don
t know how to fix it. Here I upload my small test class to demonstrate this issue: https://gist.github.com/469db5ea0270d4524d38.gitDid you face with this error or at least know how to workaround it?
Will be apprechiate for your help.