Dx11 Issue trying to call context.MapSubresource()

Started by
1 comment, last by 21st Century Moose 11 years, 2 months ago

I am writing a class to render a 2D bitmap to the screen. Every time the position of the bitmap is changed, the positions of the vertices which make up the quad for the image need to be updated. Here is that function:


/// <summary>
        /// Modify vertices when the image is moved around the screen
        /// </summary>
        /// <param name="newPos"></param>
        private void updateVBuffer(Point newPos)
        {
            Vector3[] positions = 
            {
                    transformToD3DCoords(newPos),
                    transformToD3DCoords(new Point(newPos.X + this.Width, newPos.Y)),
                    transformToD3DCoords(new Point(newPos.X + this.Width, newPos.Y + this.Height)),
                    transformToD3DCoords(new Point(newPos.X, newPos.Y + this.Height))
            };

            //create clockwise winding order
            Vertex[] vertices = 
            {
                  new Vertex() {Normal = Vector3.Zero, Position = positions[0]},
                  new Vertex() {Normal = Vector3.Zero, Position = positions[1]},
                  new Vertex() {Normal = Vector3.Zero, Position = positions[2]},
                  new Vertex() {Normal = Vector3.Zero, Position = positions[3]},
            };

            DataBox dataBox = this.pipeline.Context.MapSubresource(this.vBuffer, MapMode.Write, MapFlags.None);
            dataBox.Data.Position = 0;
            dataBox.Data.WriteRange<Vertex>(vertices);
            dataBox.Data.Position = 0;
            this.pipeline.Context.UnmapSubresource(this.vBuffer, 0);

            //dataBox.Data.Dispose();
        }

In addition, here is the code where I create the index and vertex buffers:


public Bitmap(Rectangle screenBounds, D3DPipeline pipeline, Texture2D texture)
        {
            this.pipeline = pipeline;
            this.Texture = texture;
            this.Position = Point.Empty;
            this.screenBounds = screenBounds;

            BufferDescription vBufferDescr = new BufferDescription()
            {
                BindFlags = BindFlags.VertexBuffer,
                CpuAccessFlags = CpuAccessFlags.Write,
                OptionFlags = ResourceOptionFlags.None,
                SizeInBytes = Marshal.SizeOf(typeof(Vertex)) * 4,
                StructureByteStride = Marshal.SizeOf(typeof(Vertex)),
                Usage = ResourceUsage.Dynamic
            };
            vBuffer = new SlimDX.Direct3D11.Buffer(this.pipeline.Device, vBufferDescr);
            this.vBufferBinding = new VertexBufferBinding(this.vBuffer, Marshal.SizeOf(typeof(Vertex)), 0);

            BufferDescription iBufferDescr = new BufferDescription() 
            {
                BindFlags = BindFlags.IndexBuffer,
                CpuAccessFlags = CpuAccessFlags.None,
                OptionFlags = ResourceOptionFlags.None,
                SizeInBytes = Marshal.SizeOf(typeof(Int16)) * 6,
                StructureByteStride = Marshal.SizeOf(typeof(Int16)),
                Usage = ResourceUsage.Default
            };
            iBuffer = new SlimDX.Direct3D11.Buffer(this.pipeline.Device, iBufferDescr);

            this.textureRsrcView = new ShaderResourceView(pipeline.Device, this.Texture);

            this.updateVBuffer(new Point(0, 0));
        }

The exception (E_INVALIDARG) gets thrown on the line where I call context.MapSubresource() in updateVBuffer().

Any ideas on what I'm doing wrong?

J.W.
Advertisement

To get more detailed error information, you'll want to create your device with the DeviceCreationFlags.Debug flag passed to the constructor. If you do this and enable native code debugging* (it's a checkbox under the Debug section of your project properties) you'll get get descriptive error and warning messages in the
debugger output window. In cases like these they will usually tell you exactly what you're doing wrong.
In this particular case you probably just need to pass MapMode.WriteDiscard instead of MapMode.Write. WriteDiscard is the common pattern for dynamic resources, where you invalidate the previous contents and completely fill the buffer with new contents.

*This isn't available if you're using Visual C# Express, but you can use a seperate program such as DebugView to view the native debugger output.

This is buried somewhere in the D3D documentation (no, it's not where you'd expect it to be - the writeups for map or usage), and I haven't had much luck finding it now, but here's a link to part of the Ogre source code that confirms it: https://bitbucket.org/sinbad/ogre/src/a2bd59de2d6d/RenderSystems/Direct3D11/src/OgreD3D11HardwareBuffer.cpp

Basically, the only map types that are valid with a dynamic resource are discard or no-overwrite; you can't just do a regular write mapping, so hence the E_INVALIDARG.

One alternative option for you would be to use UpdateSubresource instead with a default usage buffer; I'm not familiar with the SlimDX implementation of this though.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

This topic is closed to new replies.

Advertisement