diff --git a/Diamond/Diamond.csproj b/Diamond/Diamond.csproj index 1cc8002..6cd34ea 100644 --- a/Diamond/Diamond.csproj +++ b/Diamond/Diamond.csproj @@ -34,6 +34,9 @@ ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + + ..\packages\NLog.4.4.3\lib\net45\NLog.dll + ..\packages\OpenTK.2.0.0\lib\net20\OpenTK.dll @@ -61,6 +64,12 @@ + + Always + + + Designer + diff --git a/Diamond/GLObject.cs b/Diamond/GLObject.cs index a12b26a..56e8621 100644 --- a/Diamond/GLObject.cs +++ b/Diamond/GLObject.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using OpenTK.Graphics; +using NLog; namespace Diamond { @@ -9,6 +10,11 @@ namespace Diamond /// public abstract class GLObject : IDisposable { + /// + /// Logger for this class + /// + protected Logger Log { get; private set; } + /// /// The name of this object /// @@ -21,6 +27,9 @@ namespace Diamond protected GLObject(uint id) { Id = id; + + Log = LogManager.GetLogger(GetType().FullName); + Log.Trace("Created {0}", this); } /// @@ -35,10 +44,12 @@ namespace Diamond { if (GraphicsContext.CurrentContext == null) { - Debug.WriteLine($"No current context, assuming {GetType().Name} {Id} is disposed.", "Warning"); + Log.Warn("No current context, assuming {0} is disposed.", this); return; } + Delete(); + Log.Trace("Disposed {0}", this); GC.SuppressFinalize(this); } @@ -47,6 +58,8 @@ namespace Diamond Dispose(); } + public override string ToString() => $"{GetType().Name} {Id}"; + public static explicit operator uint(GLObject o) => o.Id; public static explicit operator int(GLObject o) => (int) o.Id; } diff --git a/Diamond/NLog.config b/Diamond/NLog.config new file mode 100644 index 0000000..2c561a4 --- /dev/null +++ b/Diamond/NLog.config @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + diff --git a/Diamond/NLog.xsd b/Diamond/NLog.xsd new file mode 100644 index 0000000..946b2ea --- /dev/null +++ b/Diamond/NLog.xsd @@ -0,0 +1,2933 @@ + + + + + + + + + + + + + + + Watch config file for changes and reload automatically. + + + + + Print internal NLog messages to the console. Default value is: false + + + + + Print internal NLog messages to the console error output. Default value is: false + + + + + Write internal NLog messages to the specified file. + + + + + Log level threshold for internal log messages. Default value is: Info. + + + + + Global log level threshold for application log messages. Messages below this level won't be logged.. + + + + + Pass NLog internal exceptions to the application. Default value is: false. + + + + + Write internal NLog messages to the the System.Diagnostics.Trace. Default value is: false + + + + + + + + + + + + + + Make all targets within this section asynchronous (creates additional threads but the calling thread isn't blocked by any target writes). + + + + + + + + + + + + + + + + + Prefix for targets/layout renderers/filters/conditions loaded from this assembly. + + + + + Load NLog extensions from the specified file (*.dll) + + + + + Load NLog extensions from the specified assembly. Assembly name should be fully qualified. + + + + + + + + + + Name of the logger. May include '*' character which acts like a wildcard. Allowed forms are: *, Name, *Name, Name* and *Name* + + + + + Comma separated list of levels that this rule matches. + + + + + Minimum level that this rule matches. + + + + + Maximum level that this rule matches. + + + + + Level that this rule matches. + + + + + Comma separated list of target names. + + + + + Ignore further rules if this one matches. + + + + + Enable or disable logging rule. Disabled rules are ignored. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the file to be included. The name is relative to the name of the current config file. + + + + + Ignore any errors in the include file. + + + + + + + Variable name. + + + + + Variable value. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Number of log events that should be processed in a batch by the lazy writer thread. + + + + + Limit of full s to write before yielding into Performance is better when writing many small batches, than writing a single large batch + + + + + Action to be taken when the lazy writer thread request queue count exceeds the set limit. + + + + + Limit on the number of requests in the lazy writer thread request queue. + + + + + Time in milliseconds to sleep between batches. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Condition expression. Log events who meet this condition will cause a flush on the wrapped target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Number of log events to be buffered. + + + + + Timeout (in milliseconds) after which the contents of buffer will be flushed if there's no write in the specified period of time. Use -1 to disable timed flushes. + + + + + Indicates whether to use sliding timeout. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Encoding to be used. + + + + + Instance of that is used to format log messages. + + + + + End of line value if a newline is appended at the end of log message . + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Maximum current connections. 0 = no maximum. + + + + + Indicates whether to keep connection open whenever possible. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Network address. + + + + + Maximum queue size. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include source info (file name and line number) in the information sent over the network. + + + + + Indicates whether to include NLog-specific extensions to log4j schema. + + + + + Indicates whether to include stack contents. + + + + + Indicates whether to include call site (class and method name) in the information sent over the network. + + + + + AppInfo field. By default it's the friendly name of the current AppDomain. + + + + + NDC item separator. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + Layout that should be use to calcuate the value for the parameter. + + + + + Viewer parameter name. + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether to use default row highlighting rules. + + + + + Indicates whether to auto-check if the console is available. - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App) + + + + + The encoding for writing messages to the . + + + + + Indicates whether the error stream (stderr) should be used instead of the output stream (stdout). + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Condition that must be met in order to set the specified foreground and background color. + + + + + Background color. + + + + + Foreground color. + + + + + + + + + + + + + + + + Indicates whether to ignore case when comparing texts. + + + + + Regular expression to be matched. You must specify either text or regex. + + + + + Text to be matched. You must specify either text or regex. + + + + + Indicates whether to match whole words only. + + + + + Compile the ? This can improve the performance, but at the costs of more memory usage. If false, the Regex Cache is used. + + + + + Background color. + + + + + Foreground color. + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether to send the log messages to the standard error instead of the standard output. + + + + + Indicates whether to auto-check if the console is available - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App) + + + + + The encoding for writing messages to the . + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Obsolete - value will be ignored! The logging code always runs outside of transaction. Gets or sets a value indicating whether to use database transactions. Some data providers require this. + + + + + Database user name. If the ConnectionString is not provided this value will be used to construct the "User ID=" part of the connection string. + + + + + Name of the database provider. + + + + + Database password. If the ConnectionString is not provided this value will be used to construct the "Password=" part of the connection string. + + + + + Indicates whether to keep the database connection open between the log events. + + + + + Database name. If the ConnectionString is not provided this value will be used to construct the "Database=" part of the connection string. + + + + + Name of the connection string (as specified in <connectionStrings> configuration section. + + + + + Connection string. When provided, it overrides the values specified in DBHost, DBUserName, DBPassword, DBDatabase. + + + + + Database host name. If the ConnectionString is not provided this value will be used to construct the "Server=" part of the connection string. + + + + + Connection string using for installation and uninstallation. If not provided, regular ConnectionString is being used. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Text of the SQL command to be run on each log level. + + + + + ShaderType of the SQL command to be run on each log level. + + + + + + + + + + + + + + + + + + + + + + + ShaderType of the command. + + + + + Connection string to run the command against. If not provided, connection string from the target is used. + + + + + Indicates whether to ignore failures. + + + + + Command text. + + + + + + + + + + + + + + Layout that should be use to calcuate the value for the parameter. + + + + + Database parameter name. + + + + + Database parameter precision. + + + + + Database parameter scale. + + + + + Database parameter size. + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Layout that renders event Category. + + + + + Layout that renders event ID. + + + + + Name of the Event Log to write to. This can be System, Application or any user-defined name. + + + + + Name of the machine on which Event Log service is running. + + + + + Value to be used as the event Source. + + + + + Action to take if the message is larger than the option. + + + + + Optional entryshaderType. When not set, or when not convertable to then determined by + + + + + Message length limit to write to the Event Log. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Indicates whether to return to the first target after any successful write. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + File encoding. + + + + + Line ending mode. + + + + + Way file archives are numbered. + + + + + Name of the file to be used for an archive. + + + + + Indicates whether to automatically archive log files every time the specified time passes. + + + + + Size in bytes above which log files will be automatically archived. Warning: combining this with isn't supported. We cannot create multiple archive files, if they should have the same name. Choose: + + + + + Indicates whether to compress archive files into the zip archive format. + + + + + Maximum number of archive files that should be kept. + + + + + Gets or set a value indicating whether a managed file stream is forced, instead of using the native implementation. + + + + + Is the an absolute or relative path? + + + + + Cleanup invalid values in a filename, e.g. slashes in a filename. If set to true, this can impact the performance of massive writes. If set to false, nothing gets written when the filename is wrong. + + + + + Whether or not this target should just discard all data that its asked to write. Mostly used for when testing NLog Stack except final write + + + + + Is the an absolute or relative path? + + + + + Value indicationg whether file creation calls should be synchronized by a system global mutex. + + + + + Indicates whether the footer should be written only when the file is archived. + + + + + Name of the file to write to. + + + + + Value specifying the date format to use when archiving files. + + + + + Indicates whether to archive old log file on startup. + + + + + Indicates whether to create directories if they do not exist. + + + + + Indicates whether to enable log file(s) to be deleted. + + + + + File attributes (Windows only). + + + + + Indicates whether to delete old log file on startup. + + + + + Indicates whether to replace file contents on each write instead of appending log message at the end. + + + + + Indicates whether concurrent writes to the log file by multiple processes on the same host. + + + + + Indicates whether to keep log file open instead of opening and closing it on each logging event. + + + + + Maximum number of log filenames that should be stored as existing. + + + + + Indicates whether concurrent writes to the log file by multiple processes on different network hosts. + + + + + Number of files to be kept open. Setting this to a higher value may improve performance in a situation where a single File target is writing to many files (such as splitting by level or by logger). + + + + + Maximum number of seconds that files are kept open. If this number is negative the files are not automatically closed after a period of inactivity. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Log file buffer size in bytes. + + + + + Indicates whether to automatically flush the file buffers after each log message. + + + + + Delay in milliseconds to wait before attempting to write to the file again. + + + + + Number of times the write is appended on the file before NLog discards the log message. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Condition expression. Log events who meet this condition will be forwarded to the wrapped target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Windows domain name to change context to. + + + + + Required impersonation level. + + + + + ShaderType of the logon provider. + + + + + Logon ShaderType. + + + + + User account password. + + + + + Indicates whether to revert to the credentials of the process instead of impersonating another user. + + + + + Username to change context to. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Interval in which messages will be written up to the number of messages. + + + + + Maximum allowed number of messages written per . + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Endpoint address. + + + + + Name of the endpoint configuration in WCF configuration file. + + + + + Indicates whether to use a WCF service contract that is one way (fire and forget) or two way (request-reply) + + + + + Client ID. + + + + + Indicates whether to include per-event properties in the payload sent to the server. + + + + + Indicates whether to use binary message encoding. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + Layout that should be use to calculate the value for the parameter. + + + + + Name of the parameter. + + + + + ShaderType of the parameter. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether to send message as HTML instead of plain text. + + + + + Encoding to be used for sending e-mail. + + + + + Indicates whether to add new lines between log entries. + + + + + CC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + Recipients' email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + BCC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + Mail message body (repeated for each log message send in one mail). + + + + + Mail subject. + + + + + Sender's email address (e.g. joe@domain.com). + + + + + Indicates the SMTP client timeout. + + + + + Priority used for sending mails. + + + + + Indicates whether NewLine characters in the body should be replaced with tags. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + SMTP Server to be used for sending. + + + + + SMTP Authentication mode. + + + + + Username used to connect to SMTP server (used when SmtpAuthentication is set to "basic"). + + + + + Password used to authenticate against SMTP server (used when SmtpAuthentication is set to "basic"). + + + + + Indicates whether SSL (secure sockets layer) should be used when communicating with SMTP server. + + + + + Port number that SMTP Server is listening on. + + + + + Indicates whether the default Settings from System.Net.MailSettings should be used. + + + + + Folder where applications save mail messages to be processed by the local SMTP server. + + + + + Specifies how outgoing email messages will be handled. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Encoding to be used when writing text to the queue. + + + + + Indicates whether to use the XML format when serializing message. This will also disable creating queues. + + + + + Indicates whether to check if a queue exists before writing to it. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Indicates whether to create the queue if it doesn't exists. + + + + + Label to associate with each message. + + + + + Name of the queue to write to. + + + + + Indicates whether to use recoverable messages (with guaranteed delivery). + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Class name. + + + + + Method name. The method must be public and static. Use the AssemblyQualifiedName , https://msdn.microsoft.com/en-us/library/system.shaderType.assemblyqualifiedname(v=vs.110).aspx e.g. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Encoding to be used. + + + + + End of line value if a newline is appended at the end of log message . + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Network address. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Indicates whether to keep connection open whenever possible. + + + + + Maximum current connections. 0 = no maximum. + + + + + Maximum queue size. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Encoding to be used. + + + + + Instance of that is used to format log messages. + + + + + End of line value if a newline is appended at the end of log message . + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Maximum current connections. 0 = no maximum. + + + + + Indicates whether to keep connection open whenever possible. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Network address. + + + + + Maximum queue size. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include source info (file name and line number) in the information sent over the network. + + + + + Indicates whether to include NLog-specific extensions to log4j schema. + + + + + Indicates whether to include stack contents. + + + + + Indicates whether to include call site (class and method name) in the information sent over the network. + + + + + AppInfo field. By default it's the friendly name of the current AppDomain. + + + + + NDC item separator. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Indicates whether to perform layout calculation. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Indicates whether performance counter should be automatically created. + + + + + Name of the performance counter category. + + + + + Counter help text. + + + + + Name of the performance counter. + + + + + Performance counter shaderType. + + + + + The value by which to increment the counter. + + + + + Performance counter instance name. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Default filter to be applied when no specific rule matches. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + Condition to be tested. + + + + + Resulting filter to be applied when the condition matches. + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Number of times to repeat each log message. + + + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Number of retries that should be attempted on the wrapped target in case of a failure. + + + + + Time to wait between retries in milliseconds. + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Should we include the BOM (Byte-order-mark) for UTF? Influences the property. This will only work for UTF-8. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Encoding. + + + + + Value whether escaping be done according to the old NLog style (Very non-standard) + + + + + Value whether escaping be done according to Rfc3986 (Supports Internationalized Resource Identifiers - IRIs) + + + + + Web service method name. Only used with Soap. + + + + + Web service namespace. Only used with Soap. + + + + + Protocol to be used when calling web service. + + + + + Web service URL. + + + + + Name of the root XML element, if POST of XML document chosen. If so, this property must not be null. (see and ). + + + + + (optional) root namespace of the XML document, if POST of XML document chosen. (see and ). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Footer layout. + + + + + Header layout. + + + + + Body layout (can be repeated multiple times). + + + + + Custom column delimiter value (valid when ColumnDelimiter is set to 'Custom'). + + + + + Column delimiter. + + + + + Quote Character. + + + + + Quoting mode. + + + + + Indicates whether CVS should include header. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Layout of the column. + + + + + Name of the column. + + + + + + + + + + + + + + + + List of property names to exclude when is true + + + + + Option to include all properties from the log events + + + + + Option to render the empty object value {} + + + + + Option to suppress the extra spaces in the output json + + + + + + + + + + + + + + Determines wether or not this attribute will be Json encoded. + + + + + Layout that will be rendered as the attribute's value. + + + + + Name of the attribute. + + + + + + + + + + + + + + Footer layout. + + + + + Header layout. + + + + + Body layout (can be repeated multiple times). + + + + + + + + + + + + + + + + + + + + + Layout text. + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Condition expression. + + + + + + + + + + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + Substring to be matched. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + String to compare the layout to. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + Substring to be matched. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + String to compare the layout to. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Diamond/Shaders/Program.cs b/Diamond/Shaders/Program.cs index d3a9452..acb1bee 100644 --- a/Diamond/Shaders/Program.cs +++ b/Diamond/Shaders/Program.cs @@ -9,19 +9,25 @@ namespace Diamond.Shaders { public static Program Current { get; private set; } - private Dictionary uniforms = new Dictionary(); - private Dictionary attributes = new Dictionary(); + private readonly Dictionary _uniforms = new Dictionary(); + private readonly Dictionary _attributes = new Dictionary(); - public string Log => GL.GetProgramInfoLog((int) Id).Trim(); + public string InfoLog => GL.GetProgramInfoLog((int) Id).Trim(); public Program() : base((uint) GL.CreateProgram()) { } - protected override void Delete() => GL.DeleteProgram(Id); + protected override void Delete() + { + GL.DeleteProgram(Id); + } - public void Attach(Shader shader) => GL.AttachShader(Id, shader.Id); + public void Attach(Shader shader) + { + GL.AttachShader(Id, shader.Id); + } public bool Linked { @@ -34,18 +40,26 @@ namespace Diamond.Shaders public bool Link() { - uniforms.Clear(); - attributes.Clear(); + _uniforms.Clear(); + _attributes.Clear(); + GL.LinkProgram(Id); - GL.GetProgram(Id, GetProgramParameterName.LinkStatus, out int success); - if (success == 0) return false; + + if (!Linked) + { + Log.Warn("Failed to link Program {0}", Id); + Log.Debug("Program {0} InfoLog\n{1}", Id, InfoLog); + return false; + } + + Log.Info("Successfully linked Program {0}", Id); GL.GetProgram(Id, GetProgramParameterName.ActiveUniforms, out int uniformcount); for (var i = 0; i < uniformcount; i++) { var sb = new StringBuilder(256); GL.GetActiveUniformName((int) Id, i, sb.Capacity, out int length, sb); - uniforms[sb.ToString()] = i; + _uniforms[sb.ToString()] = i; } GL.GetProgram(Id, GetProgramParameterName.ActiveAttributes, out int attributecount); @@ -54,7 +68,7 @@ namespace Diamond.Shaders var sb = new StringBuilder(256); GL.GetActiveAttrib((int) Id, i, sb.Capacity, out int length, out int size, out ActiveAttribType type, sb); - attributes[sb.ToString()] = i; + _attributes[sb.ToString()] = i; } return true; @@ -62,26 +76,28 @@ namespace Diamond.Shaders public bool TryGetUniform(string name, out int id) { - return uniforms.TryGetValue(name, out id); + return _uniforms.TryGetValue(name, out id); } public int GetUniform(string name) { - if (!TryGetUniform(name, out int id)) - throw new ShaderException($"Shader Program {Id} does not contain uniform '{name}'"); - return id; + if (TryGetUniform(name, out int id)) return id; + + Log.Warn("Attempted to access uniform {0} on Program {1}", name, Id); + throw new ShaderException($"Shader Program {Id} does not contain uniform '{name}'"); } public bool TryGetAttribute(string name, out int id) { - return attributes.TryGetValue(name, out id); + return _attributes.TryGetValue(name, out id); } public int GetAttribute(string name) { - if (!TryGetAttribute(name, out int id)) - throw new ShaderException($"Shader Program {Id} does not contain id '{name}'"); - return id; + if (TryGetAttribute(name, out int id)) return id; + + Log.Warn("Attempted to access attribute {0} on Program {1}", name, Id); + throw new ShaderException($"Shader Program {Id} does not contain id '{name}'"); } public void SetAttribPointers(GLBuffer buff) where T : struct @@ -92,10 +108,11 @@ namespace Diamond.Shaders foreach (var attr in vdi.Pointers) { if (!TryGetAttribute(attr.Name, out int loc)) continue; + GL.VertexAttribPointer(loc, attr.Size, attr.Type, attr.Normalized, vdi.Stride, attr.Offset); } } - + public void Use() { GL.UseProgram(Id); @@ -111,11 +128,29 @@ namespace Diamond.Shaders public static Program FromShaders(params Shader[] shaders) { var p = new Program(); + foreach (var shader in shaders) { p.Attach(shader); } + p.Link(); + + return p; + } + + public static Program FromFiles(params string[] files) + { + var shaders = new Shader[files.Length]; + + for (var i = 0; i < files.Length; i++) + shaders[i] = Shader.FromFile(files[i]); + + var p = FromShaders(shaders); + + for (var i = 0; i < shaders.Length; i++) + shaders[i]?.Dispose(); + return p; } } diff --git a/Diamond/Shaders/Shader.cs b/Diamond/Shaders/Shader.cs index 0ce79ad..9a18954 100644 --- a/Diamond/Shaders/Shader.cs +++ b/Diamond/Shaders/Shader.cs @@ -12,7 +12,7 @@ namespace Diamond.Shaders /// /// The type of this shader. /// - public readonly ShaderType Type; + public readonly ShaderType ShaderType; /// /// The source file name, if it was loaded from a file. @@ -36,7 +36,7 @@ namespace Diamond.Shaders /// /// Retrieves this shader's compilation log with glGetShaderInfoLog. /// - public string Log => GL.GetShaderInfoLog((int) Id).Trim(); + public string InfoLog => GL.GetShaderInfoLog((int) Id).Trim(); /// /// Checks the compilation status of this shader with glGetShader. @@ -53,11 +53,11 @@ namespace Diamond.Shaders /// /// Creates a wrapper for a gl Shader object. /// - /// The type of the shader to create - public Shader(ShaderType type) - : base((uint) GL.CreateShader(type)) + /// The type of the shader to create + public Shader(ShaderType shaderType) + : base((uint) GL.CreateShader(shaderType)) { - Type = type; + ShaderType = shaderType; } protected override void Delete() => GL.DeleteShader(Id); @@ -69,7 +69,46 @@ namespace Diamond.Shaders public bool Compile() { GL.CompileShader(Id); - return Compiled; + + var compiled = Compiled; + if (!compiled) + { + Log.Warn("Failed to compile {0} {1} {2}", ShaderType, Id, SourceFile); + Log.Debug("{0} {1} InfoLog\n{2}", ShaderType, Id, InfoLog); + } + + return compiled; + } + + /// + /// Creates and compiles a shader from a source file. Infers shader type from file extension + /// Extension must be of the form .[type] or .[type].glsl + /// Valid types are vs, vert, fs, and frag. + /// + /// Source file location + /// The compiled shader + public static Shader FromFile(string path) + { + var ex = Path.GetExtension(path); + + if (ex == ".glsl") + { + var name = Path.GetFileNameWithoutExtension(path); + if (Path.HasExtension(name)) + ex = Path.GetExtension(name); + } + + switch (ex) + { + case ".vs": + case ".vert": + return FromFile(path, ShaderType.VertexShader); + case ".fs": + case ".frag": + return FromFile(path, ShaderType.FragmentShader); + default: + throw new ShaderException("Can't infer shader type from extension"); + } } /// @@ -79,25 +118,14 @@ namespace Diamond.Shaders /// Type of the shader /// The compiled shader public static Shader FromFile(string path, ShaderType type) - { - return FromFile(path, type, out bool success); - } - - /// - /// Creates and compiles a shader from a source file. - /// - /// Source file location - /// Type of the shader - /// Compilation success - /// The compiled shader - public static Shader FromFile(string path, ShaderType type, out bool success) { var s = new Shader(type) { Source = File.ReadAllText(path), - SourceFile = "" + SourceFile = path }; - success = s.Compile(); + + s.Compile(); return s; } } diff --git a/Diamond/packages.config b/Diamond/packages.config index dfa0316..9436aee 100644 --- a/Diamond/packages.config +++ b/Diamond/packages.config @@ -1,5 +1,8 @@  + + + \ No newline at end of file diff --git a/hexworld/HexRender.cs b/hexworld/HexRender.cs index 04fd13b..d01cf90 100644 --- a/hexworld/HexRender.cs +++ b/hexworld/HexRender.cs @@ -83,49 +83,8 @@ namespace hexworld { base.OnLoad(e); - using (var vs = Shader.FromFile(@"res\s.vs.glsl", ShaderType.VertexShader)) - using (var fs = Shader.FromFile(@"res\s.fs.glsl", ShaderType.FragmentShader)) - { - if (!vs.Compiled | !fs.Compiled) - { - Debug.WriteLine("Failed to compile shaders:"); - Debug.WriteLineIf(!vs.Compiled, $"Vertex Log ({vs.Id}):\n{vs.Log}"); - Debug.WriteLineIf(!fs.Compiled, $"Fragment Log ({fs.Id}):\n{fs.Log}"); - Exit(); - return; - } - - _jsonPgm = Program.FromShaders(vs, fs); - - if (!_jsonPgm.Link()) - { - Debug.WriteLine($"Failed to link program ({_jsonPgm.Id}):\n{_jsonPgm.Log}"); - Exit(); - return; - } - } - - using (var vs = Shader.FromFile(@"res\obj.vs.glsl", ShaderType.VertexShader)) - using (var fs = Shader.FromFile(@"res\obj.fs.glsl", ShaderType.FragmentShader)) - { - if (!vs.Compiled | !fs.Compiled) - { - Debug.WriteLine("Failed to compile shaders:"); - Debug.WriteLineIf(!vs.Compiled, $"Vertex Log ({vs.Id}):\n{vs.Log}"); - Debug.WriteLineIf(!fs.Compiled, $"Fragment Log ({fs.Id}):\n{fs.Log}"); - Exit(); - return; - } - - _objPgm = Program.FromShaders(vs, fs); - - if (!_objPgm.Link()) - { - Debug.WriteLine($"Failed to link program ({_objPgm.Id}):\n{_jsonPgm.Log}"); - Exit(); - return; - } - } + _jsonPgm = Program.FromFiles(@"res\s.vs.glsl", @"res\s.fs.glsl"); + _objPgm = Program.FromFiles(@"res\obj.vs.glsl", @"res\obj.fs.glsl"); _cubeMesh = Mesh.FromJson(@"res\data_vert_cubes.json"); _panelMesh = Mesh.FromJson(@"res\data_vert_panels.json"); @@ -141,7 +100,6 @@ namespace hexworld _tableTiles = new SubArray( JsonConvert.DeserializeObject(File.ReadAllText(@"res\data_tile_table.json"))); - _allTiles = SubArray.Join(_stoneTiles, _grassTiles, _grayTiles, _tableTiles); _tileBuffer = new GLBuffer(BufferTarget.ArrayBuffer, BufferUsageHint.DynamicDraw); _tileBuffer.Data(_allTiles); @@ -196,42 +154,52 @@ namespace hexworld GL.DepthFunc(DepthFunction.Lequal); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); -// GL.Enable(EnableCap.CullFace); -// GL.CullFace(CullFaceMode.Back); + GL.Enable(EnableCap.CullFace); + GL.CullFace(CullFaceMode.Back); - _jsonPgm.Use(); + if (_jsonPgm.Linked) + { + _jsonPgm.Use(); - _jsonPgm.SetAttribPointers(_tileBuffer); - _jsonPgm.SetAttribPointers(_vertexBuffer); + _jsonPgm.SetAttribPointers(_tileBuffer); + _jsonPgm.SetAttribPointers(_vertexBuffer); - _grass.Bind(0); - _stone.Bind(1); - _gray.Bind(2); + _grass.Bind(0); + _stone.Bind(1); + _gray.Bind(2); - GL.Uniform1(_jsonPgm.GetUniform("tex"), 0); - GL.UniformMatrix4(_jsonPgm.GetUniform("view"), false, ref _view); - GL.UniformMatrix4(_jsonPgm.GetUniform("proj"), false, ref _proj); + GL.Uniform1(_jsonPgm.GetUniform("tex"), 0); + GL.UniformMatrix4(_jsonPgm.GetUniform("view"), false, ref _view); + GL.UniformMatrix4(_jsonPgm.GetUniform("proj"), false, ref _proj); - _cubeMesh.DrawInstanced(_grassTiles); + _cubeMesh.DrawInstanced(_grassTiles); - GL.Uniform1(_jsonPgm.GetUniform("tex"), 1); + GL.Uniform1(_jsonPgm.GetUniform("tex"), 1); - _panelMesh.DrawInstanced(_stoneTiles); + _panelMesh.DrawInstanced(_stoneTiles); - GL.Uniform1(_jsonPgm.GetUniform("tex"), 2); + GL.Uniform1(_jsonPgm.GetUniform("tex"), 2); - _sidesMesh.DrawInstanced(_grayTiles); + _sidesMesh.DrawInstanced(_grayTiles); + } - _objPgm.Use(); + if (_objPgm.Linked) + { + _objPgm.Use(); - _objPgm.SetAttribPointers(_tileBuffer); - _objPgm.SetAttribPointers(_objBuffer); + _grass.Bind(0); + _stone.Bind(1); + _gray.Bind(2); - GL.Uniform1(_jsonPgm.GetUniform("tex"), 2); - GL.UniformMatrix4(_jsonPgm.GetUniform("view"), false, ref _view); - GL.UniformMatrix4(_jsonPgm.GetUniform("proj"), false, ref _proj); + _objPgm.SetAttribPointers(_tileBuffer); + _objPgm.SetAttribPointers(_objBuffer); - _objMesh.DrawInstanced(_tableTiles); + GL.Uniform1(_objPgm.GetUniform("tex"), 2); + GL.UniformMatrix4(_objPgm.GetUniform("view"), false, ref _view); + GL.UniformMatrix4(_objPgm.GetUniform("proj"), false, ref _proj); + + _objMesh.DrawInstanced(_tableTiles); + } SwapBuffers(); } diff --git a/hexworld/res/obj.fs.glsl b/hexworld/res/obj.fs.glsl index 632231d..85ae45d 100644 --- a/hexworld/res/obj.fs.glsl +++ b/hexworld/res/obj.fs.glsl @@ -5,10 +5,9 @@ in float light; uniform sampler2D tex; -void main () +void main ()l { vec4 color = texture(tex, vcoord); - color.w = 1; color.xyz *= light; gl_FragColor = clamp(color, 0, 1); } \ No newline at end of file