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

context.OMSetRenderTargets don't make effective in my App #471

Open
KnewHow opened this issue Dec 11, 2024 · 1 comment
Open

context.OMSetRenderTargets don't make effective in my App #471

KnewHow opened this issue Dec 11, 2024 · 1 comment

Comments

@KnewHow
Copy link

KnewHow commented Dec 11, 2024

I am writing an render program with Vortice.windows, I use c# wpf as picture display and TqkLibrary.Wpf.Interop.DirectX.D3D11Image as wpf image source.
I create my device use following code,

public static readonly FeatureLevel[] S_FEATURELEVELS =
[
    FeatureLevel.Level_11_1,
    FeatureLevel.Level_11_0,
];
_dxgiFactory = CreateDXGIFactory1<IDXGIFactory2>();
_colorFormat = Format.B8G8R8A8_UNorm;
_depthStencilFormat = Format.D32_Float;
creationFlags = DeviceCreationFlags.BgraSupport | DeviceCreationFlags.Debug;
using (IDXGIFactory5? factory5 = _dxgiFactory.QueryInterfaceOrNull<IDXGIFactory5>())
{
    if (factory5 != null)
    {
        _isTearingSupported = factory5.PresentAllowTearing;
    }
}

this.Device = D3D11CreateDevice(DriverType.Hardware, creationFlags, S_FEATURELEVELS);
this.DeviceContext = this.Device.ImmediateContext;

And all canvas and actor use the same device.

Then, I init my renderTarget in my canvas, I has two kinds of canvas, one is 2D and another is 3D
2D canvas is:

/// <summary>
/// 渲染的结果数据, 是wpf的 image的数据源
/// </summary>
public TqkLibrary.Wpf.Interop.DirectX.D3D11Image image { get; private set; }
/// <summary>
/// 渲染的renderTarget
/// </summary>
public ID3D11Texture2D? renderTarget { get; private set; }
/// <summary>
/// 渲染的renderTargetView
/// </summary>
public ID3D11RenderTargetView? renderTargetView { get; private set; }
/// <summary>
/// 渲染的renderTarget 2D
/// </summary>
public ID2D1RenderTarget? renderTarget_2d { get; private set; }
/// <summary>
/// 画布的d2DFactory
/// </summary>
public ID2D1Factory d2DFactory { get; private set; }

public Canvas2D(nint windowOwner)
{
    this.d2DFactory = D2D1.D2D1CreateFactory<ID2D1Factory>();
    image = new TqkLibrary.Wpf.Interop.DirectX.D3D11Image();
    image.WindowOwner = windowOwner;
    image.OnRender += OnRender;
    image.SetPixelSize(100, 100);
}

private void OnRender(IntPtr resourcePtr, bool isNewSurface)
{
    if (isNewSurface)
    {
        InitializeTextureAndBuffers(resourcePtr);
    }
}

private void InitializeTextureAndBuffers(IntPtr resourcePtr)
{
    this.renderTargetView?.Dispose();
    this.renderTarget_2d?.Dispose();
    this.renderTarget?.Dispose();

    Vortice.DXGI.IDXGIResource1 resource = new IDXGIResource1(resourcePtr).QueryInterface<Vortice.DXGI.IDXGIResource1>();
    this.renderTarget = device.OpenSharedResource<ID3D11Texture2D>(resource.SharedHandle);
    this.renderTargetView = device.CreateRenderTargetView(this.renderTarget);
    Vortice.DXGI.IDXGISurface surface = renderTarget.QueryInterface<Vortice.DXGI.IDXGISurface>();
    var renderTargetProperties = new RenderTargetProperties(Vortice.DCommon.PixelFormat.Premultiplied);
    this.renderTarget_2d = this.d2DFactory.CreateDxgiSurfaceRenderTarget(surface, renderTargetProperties);
    surface.Dispose();
    resource.Dispose();
}

public override void redraw()
{

    _renderTimeStamp = DateTime.Now.Ticks;
    if (visible && _width > 0 && _height > 0)
    {
        int w = _width, h = _height;
        if (visible && w > 0 && h > 0)
        {
            if (_isSizeChanged)
            {
                image.SetPixelSize(w, h);
                _isSizeChanged = false;
            }
            if (renderTargetView != null)
            {
                var context = device.ImmediateContext;
                context.UnsetRenderTargets();
                Color4 backgroundColor = new Color4(1.0f, 0, 0, 1);
                context.ClearRenderTargetView(renderTargetView, backgroundColor);
                context.ClearDepthStencilView(depthStencilView, DepthStencilClearFlags.Depth, 1.0f, 0);
                context.RSSetViewport(0, 0, w, h, 0.0f, 1.0f);
                // 设置深度测试操作
                context.IASetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
                context.OMSetDepthStencilState(depthStencilState, 1);
                context.OMSetRenderTargets(this.renderTargetView, depthStencilView);
                image.Lock();
                context.ClearRenderTargetView(this.renderTargetView, new Color4(0, 0, 0, 1));
                context.RSSetState(GlobalEngine.Instance.noneRasterizerState);
                renderTarget_2d?.BeginDraw();
                Console.WriteLine($"2d canvas set targets{this.renderTargetView}, context: {context}....");
                commandLists.Clear();
                foreach (var actor in Actors)
                {
                    actor.prepare();
                }


                foreach (var command in commandLists) // the commandList is empty now, you can ignore them
                {
                    context.ExecuteCommandList(command, true);
                    command.Dispose();
                }
                commandLists.Clear();
                foreach (var actor in Actors)
                {
                    actor.draw();
                }

                renderTarget_2d?.EndDraw();
                image.Unlock();
                context.Flush();
                image.RequestRender();

                //var task = Task.Run(() =>
                //{

                    
                //});
                //task.ContinueWith(t =>
                //{
                //    Application.Current.Dispatcher.BeginInvoke(() =>
                //    {
                        
                        
                //    });

                //});

            }
        }
    }
    image.RequestRender();
}

3D cavans is:

  public ID3D11RenderTargetView? renderTargetView { get; private set; }
  public ID3D11Texture2D? renderTarget { get; private set; }
  public ID3D11Texture2D? depthBuffer { get; private set; }
  public ID3D11DepthStencilView? depthStencilView { get; private set; }
  public ID3D11DepthStencilState? depthStencilState { get; private set; }

public Canvas3D(nint windowOwner)
{
image = new TqkLibrary.Wpf.Interop.DirectX.D3D11Image();
image.WindowOwner = windowOwner;
image.OnRender -= OnRender;
image.OnRender += OnRender;
image.SetPixelSize(100, 100);
}

private void OnRender(IntPtr resourcePtr, bool isNewSurface)
{
    if (isNewSurface)
    {
        InitializeTextureAndBuffers(resourcePtr);
    }
}

private void InitializeTextureAndBuffers(IntPtr resourcePtr)
{
    renderTargetView?.Dispose();
    renderTarget?.Dispose();
    
    Vortice.DXGI.IDXGIResource1 resource = new IDXGIResource1(resourcePtr).QueryInterface<Vortice.DXGI.IDXGIResource1>();
    this.renderTarget = device.OpenSharedResource<ID3D11Texture2D>(resource.SharedHandle);
    RenderTargetViewDescription desc = new RenderTargetViewDescription();
    desc.Format = Format.B8G8R8A8_UNorm;
    desc.ViewDimension = RenderTargetViewDimension.Texture2D;
    desc.Texture2D.MipSlice = 0;
    renderTargetView = device.CreateRenderTargetView(this.renderTarget, desc);
    resource.Dispose();
    createDepthBuffer();
}

public override void redraw()
{
    _renderTimeStamp = DateTime.Now.Ticks;
    if (visible && _width > 0 && _height > 0)
    {
        if (_isSizeChanged)
        {
            image.SetPixelSize(_width, _width);
            _isSizeChanged = false;
        }
        if(renderTargetView != null)
        {
            var context = device.ImmediateContext;
           
            Color4 bkColor = common.GUtils.vector4ToColor4(backgroundColor);
            calCameraParams();
            //context.UnsetRenderTargets();
            context.ClearRenderTargetView(renderTargetView, bkColor);
            context.ClearDepthStencilView(depthStencilView, DepthStencilClearFlags.Depth, 1.0f, 0);
            context.RSSetViewport(0, 0, _width, _height, 0.0f, 1.0f);
            // 设置深度测试操作
            context.IASetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
            context.OMSetDepthStencilState(depthStencilState, 1);
            context.ClearRenderTargetView(this.renderTargetView, new Color4(0, 0, 0, 1));
            context.OMSetRenderTargets(this.renderTargetView, this.depthStencilView);
            image.Lock();
            context.RSSetState(GlobalEngine.Instance.noneRasterizerState);
            var renderActors = actors.OrderBy(x => x.getWeight()).ThenBy(x => x.getID()).ToList();
            Console.WriteLine($"3d canvas set targets:{this.renderTargetView}, context: {context}....");
            foreach (var actor in renderActors)
            {
                //actor.blend();
                actor.draw();
                Console.WriteLine("3d canvas actor draw....");
            }
            image.Unlock();
            context.Flush();
            image.RequestRender();
            //if(renderTarget != null)
            //{
            //    VorticeResourceUtils.readFromTexture2D(device, renderTarget, (uint)_width, (uint)_height);
            //}
        }
        
    }
}

when init 2D and 3D canvas, I create some actor to draw 2D and 3D, they are will be used in 2d canvas and 3D canvas
2D actor code

ID3D11ShaderResourceView? srv = dataSource?.getTextureSRV();
if (visible && dataSource != null && canvas != null && colorMapTextureSRV != null && srv != null && canvas is SliceRenderCanvas2D sliceCanvas && sliceCanvas.renderTargetView != null)
{
    ID3D11DeviceContext context = device.ImmediateContext;
    ID3D11VertexShader vs = sliceCanvas.getSliceVS();
    ID3D11PixelShader ps = sliceCanvas.SliceImagePS;
    context.VSSetShader(vs);
    context.PSSetShader(ps);

    int width = canvas.getWidth();
    int height = canvas.getHeight();
    context.IASetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
    context.RSSetViewport(0, 0, width, height, 0.0f, 1.0f);
    context.OMSetDepthStencilState(sliceCanvas.depthStencilState, 1);
    context.OMSetRenderTargets(sliceCanvas.renderTargetView, sliceCanvas.depthStencilView);
    context.RSSetState(GlobalEngine.Instance.noneRasterizerState);
    //context.OMSetBlendState(GlobalEngine.Instance.VolumeBlendState);
    if (enableBlend)
    {
        context.OMSetBlendState(GlobalEngine.Instance.VolumeBlendState);
    }
    else
    {
        context.OMSetBlendState(null);
    }
context.Draw(4, 0);

And 3D actor code is

 var context = device.ImmediateContext;
 ID3D11VertexShader vs = canvas.ImageVS;
 ID3D11PixelShader ps = canvas.ImagePS;
 context.VSSetShader(vs);
 context.PSSetShader(ps);
 context.RSSetState(GlobalEngine.Instance.noneRasterizerState);
 context.IASetInputLayout(inputLayout);
 context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);
 MVP = Matrix4x4.Transpose(MVP);
 Matrix4x4 t = Matrix4x4.Transpose(MVP);
 MVPTransformTransformCB.SetData(context, t);
uint stride = sizeof(float) * 3;
context.IASetVertexBuffer(0, vertexBuffer, stride);
context.IASetIndexBuffer(indexBuffer, Vortice.DXGI.Format.R32_UInt, 0);
uint indexCnt = (uint)indexArray.Length;
context.DrawIndexed(indexCnt, 0, 0);
context.Flush();

The HLSL is very simple, 2D draw a CT and 3D draw cube, But I find I always draw the 3D result in 2D renderTargetView.
image
Yan can see the green cube in 2D window, it is in 3D window!

If I try use context.UnsetRenderTargets() to reset 3D canvas renderTargetView before set 3D renderTargetView, the cube will not display!
image
You can see the green cube don't display when I use context.UnsetRenderTargets() befere set renderTargetView in 3D canvas.
I try use context.UnsetRenderTargets() befere set renderTargetView in 2D canvas. The 2D render result display normal.

Why? Use same way to create RenderTargetView, Why renderTargetView who in 3D canvans is no effective when I set it?
I guess the reason is set renderTargetView no effective in 3D canvans, but I don't know where the bug it is. Can you help me find the bug?

@KnewHow
Copy link
Author

KnewHow commented Dec 13, 2024

I find my error is image.SetPixelSize(_width, _width);, it should image.SetPixelSize(_width, height);

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

No branches or pull requests

1 participant