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

...Info structures not unmarshaled. #49

Open
Y-Less opened this issue Jun 19, 2019 · 1 comment
Open

...Info structures not unmarshaled. #49

Y-Less opened this issue Jun 19, 2019 · 1 comment

Comments

@Y-Less
Copy link
Contributor

Y-Less commented Jun 19, 2019

This is mainly an issue for DebugUtilsMessengerCallbackData, which contains DebugUtilsObjectNameInfo[], and thus is transitively not unmarshalled for use in CreateDebugUtilsMessenger, I'm currently doing this:

using System;

namespace SharpVk.Multivendor
{
    public partial class DebugReportDelegate : IDisposable
    {
        private readonly SharpVk.Multivendor.DebugReportCallback callback_;
        private readonly System.Runtime.InteropServices.GCHandle gch_;

        internal DebugReportDelegate(System.Runtime.InteropServices.GCHandle gch, SharpVk.Multivendor.DebugReportCallback callback)
        {
            callback_ = callback;
            gch_ = gch;
        }

        public void Dispose()
        {
            callback_.Dispose();
            gch_.Free();
        }
    }

    public interface IDebugReportDelegate
    {
        bool DebugReportDelegate(SharpVk.Multivendor.DebugReportFlags flags, SharpVk.Multivendor.DebugReportObjectType objectType, ulong @object, HostSize location, int messageCode, string pLayerPrefix, string pMessage);
    }

    public partial class DebugUtilsDelegate : IDisposable
    {
        private readonly SharpVk.Multivendor.DebugUtilsMessenger callback_;
        private readonly System.Runtime.InteropServices.GCHandle gch_;

        internal DebugUtilsDelegate(System.Runtime.InteropServices.GCHandle gch, SharpVk.Multivendor.DebugUtilsMessenger callback)
        {
            callback_ = callback;
            gch_ = gch;
        }

        public void Dispose()
        {
            callback_.Dispose();
            gch_.Free();
        }
    }

    public interface IDebugUtilsDelegate
    {
        bool DebugUtilsDelegate(SharpVk.Multivendor.DebugUtilsMessageSeverityFlags messageSeverity, SharpVk.Multivendor.DebugUtilsMessageTypeFlags messageTypes, SharpVk.Multivendor.DebugUtilsMessengerCallbackData pCallbackDatas);
    }

    /// <summary>
    /// 
    /// </summary>
    public static class HLInstanceExtensions
    {
        /// <summary>
        /// Create a debug report callback object.
        /// </summary>
        /// <param name="extendedHandle">
        /// The Instance handle to extend.
        /// </param>
        /// <param name="flags">
        /// flags indicate which event(s) will cause this callback to be
        /// called. Flags are interpreted as bitmasks and multiple may be set.
        /// Bits which can be set include: + --
        /// </param>
        /// <param name="allocator">
        /// An optional AllocationCallbacks instance that controls host memory
        /// allocation.
        /// </param>
        public static SharpVk.Multivendor.DebugReportDelegate CreateDebugReportDelegate(this SharpVk.Instance extendedHandle, SharpVk.Multivendor.IDebugReportDelegate callback, SharpVk.Multivendor.DebugReportFlags? flags = default(SharpVk.Multivendor.DebugReportFlags?), SharpVk.AllocationCallbacks? allocator = default(SharpVk.AllocationCallbacks?))
        {
            System.Runtime.InteropServices.GCHandle gch = System.Runtime.InteropServices.GCHandle.Alloc(callback);
            try
            {
                SharpVk.Multivendor.DebugReportCallback result = extendedHandle.CreateDebugReportCallback(DebugReportDelegate, flags, System.Runtime.InteropServices.GCHandle.ToIntPtr(gch), allocator);
                return new SharpVk.Multivendor.DebugReportDelegate(gch, result);
            }
            catch
            {
                gch.Free();
                throw;
            }
        }

        private static readonly SharpVk.Multivendor.DebugReportCallbackDelegate DebugReportDelegate = DebugReport;

        private static Bool32 DebugReport(SharpVk.Multivendor.DebugReportFlags flags, SharpVk.Multivendor.DebugReportObjectType objectType, ulong @object, HostSize location, int messageCode, string pLayerPrefix, string pMessage, IntPtr pUserData)
        {
            if (pUserData == IntPtr.Zero)
            {
                return false;
            }
            System.Runtime.InteropServices.GCHandle gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(pUserData);
            IDebugReportDelegate idrd = (IDebugReportDelegate)gch.Target;
            if (idrd == null)
            {
                return false;
            }

            return idrd.DebugReportDelegate(flags, objectType, @object, location, messageCode, pLayerPrefix, pMessage);
        }

        /// <summary>
        /// Create a debug utils messenger object.
        /// </summary>
        /// <param name="extendedHandle">
        /// The Instance handle to extend.
        /// </param>
        /// <param name="flags">
        /// flags indicate which event(s) will cause this callback to be
        /// called. Flags are interpreted as bitmasks and multiple may be set.
        /// Bits which can be set include: + --
        /// </param>
        /// <param name="allocator">
        /// An optional AllocationCallbacks instance that controls host memory
        /// allocation.
        /// </param>
        public static SharpVk.Multivendor.DebugUtilsDelegate CreateDebugUtilsDelegate(this SharpVk.Instance extendedHandle, SharpVk.Multivendor.DebugUtilsMessageSeverityFlags messageSeverity, SharpVk.Multivendor.DebugUtilsMessageTypeFlags messageType, SharpVk.Multivendor.IDebugUtilsDelegate callback, SharpVk.Multivendor.DebugUtilsMessengerCreateFlags? flags = default(SharpVk.Multivendor.DebugUtilsMessengerCreateFlags?), SharpVk.AllocationCallbacks? allocator = default(SharpVk.AllocationCallbacks?))
        {
            System.Runtime.InteropServices.GCHandle gch = System.Runtime.InteropServices.GCHandle.Alloc(callback);
            try
            {
                SharpVk.Multivendor.DebugUtilsMessenger result = extendedHandle.CreateDebugUtilsMessenger(messageSeverity, messageType, DebugUtilsDelegate, flags, System.Runtime.InteropServices.GCHandle.ToIntPtr(gch), allocator);
                return new SharpVk.Multivendor.DebugUtilsDelegate(gch, result);
            }
            catch
            {
                gch.Free();
                throw;
            }
        }

        private static readonly SharpVk.Multivendor.DebugUtilsMessengerCallbackDelegate DebugUtilsDelegate = DebugUtils;

        private unsafe static SharpVk.Multivendor.DebugUtilsLabel MarshalFrom(SharpVk.Interop.Multivendor.DebugUtilsLabel* pointer)
        {
            SharpVk.Multivendor.DebugUtilsLabel result = default(SharpVk.Multivendor.DebugUtilsLabel);
            result.LabelName = pointer->LabelName == null ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(new IntPtr(pointer->LabelName));
            result.Color = (pointer->Color[0], pointer->Color[1], pointer->Color[2], pointer->Color[3]);
            return result;
        }

        private unsafe static SharpVk.Multivendor.DebugUtilsObjectNameInfo MarshalFrom(SharpVk.Interop.Multivendor.DebugUtilsObjectNameInfo* pointer)
        {
            SharpVk.Multivendor.DebugUtilsObjectNameInfo result = default(SharpVk.Multivendor.DebugUtilsObjectNameInfo);
            result.ObjectType = pointer->ObjectType;
            result.ObjectHandle = pointer->ObjectHandle;
            result.ObjectName = pointer->ObjectName == null ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(new IntPtr(pointer->ObjectName));
            return result;
        }

        private unsafe static SharpVk.Multivendor.DebugUtilsMessengerCallbackData MarshalFrom(SharpVk.Interop.Multivendor.DebugUtilsMessengerCallbackData* pointer)
        {
            SharpVk.Multivendor.DebugUtilsMessengerCallbackData result = default(SharpVk.Multivendor.DebugUtilsMessengerCallbackData);
            result.Flags = pointer->Flags;
            result.MessageIdName = pointer->MessageIdName == null ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(new IntPtr(pointer->MessageIdName));
            result.MessageIdNumber = pointer->MessageIdNumber;
            result.Message = pointer->Message == null ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(new IntPtr(pointer->Message));

            if (pointer->QueueLabels == null)
            {
                result.QueueLabels = null;
            }
            else
            {
                result.QueueLabels = new DebugUtilsLabel[pointer->QueueLabelCount];
                for (int index = 0; index < (uint)(result.QueueLabels.Length); index++)
                {
                    result.QueueLabels[index] = MarshalFrom(&pointer->QueueLabels[index]);
                }
            }

            if (pointer->CommandBufLabels == null)
            {
                result.CommandBufLabels = null;
            }
            else
            {
                result.CommandBufLabels = new DebugUtilsLabel[pointer->CommandBufLabelCount];
                for (int index = 0; index < (uint)(result.CommandBufLabels.Length); index++)
                {
                    result.CommandBufLabels[index] = MarshalFrom(&pointer->CommandBufLabels[index]);
                }
            }

            if (pointer->Objects == null)
            {
                result.Objects = null;
            }
            else
            {
                result.Objects = new DebugUtilsObjectNameInfo[pointer->ObjectCount];
                for (int index = 0; index < (uint)(result.Objects.Length); index++)
                {
                    result.Objects[index] = MarshalFrom(&pointer->Objects[index]);
                }
            }

            return result;
        }

        private static unsafe Bool32 DebugUtils(SharpVk.Multivendor.DebugUtilsMessageSeverityFlags messageSeverity, SharpVk.Multivendor.DebugUtilsMessageTypeFlags messageTypes, IntPtr pCallbackData, IntPtr pUserData)
        {
            if (pUserData == IntPtr.Zero)
            {
                return false;
            }
            System.Runtime.InteropServices.GCHandle gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(pUserData);
            IDebugUtilsDelegate idrd = (IDebugUtilsDelegate)gch.Target;
            if (idrd == null)
            {
                return false;
            }

            SharpVk.Multivendor.DebugUtilsMessengerCallbackData userData = MarshalFrom((SharpVk.Interop.Multivendor.DebugUtilsMessengerCallbackData*)pCallbackData.ToPointer());
            return idrd.DebugUtilsDelegate(messageSeverity, messageTypes, userData);
        }
    }
}

I tried to match the generated code style as much as possible, but without being able to use any of the internal HeapUtil methods.

@FacticiusVir
Copy link
Owner

The filter on "...Info" structs was likely to identify types used purely for input (e.g. CreateInfo types) which are/were not consistently identified in vk.xml; there's no handling for this case of structs as callback parameters. The current implementation of callbacks needs several improvements in any case, but the Debug Utils use case raises the priority a little.

Unless I can find a more intelligent filter to handle the input Info structs case, I'll find a subfilter for Info structs that are passed back out from the API in callback delegates.

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

2 participants