Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into onecsproj_onexkpkg2
Browse files Browse the repository at this point in the history
# Conflicts:
#	Xenko.xkpkg
#	sources/shared/SharedAssemblyInfo.cs
  • Loading branch information
xen2 committed Nov 21, 2018
2 parents 50412ba + a7db66d commit be8bb7d
Show file tree
Hide file tree
Showing 21 changed files with 180 additions and 79 deletions.
3 changes: 3 additions & 0 deletions BACKERS.md
Expand Up @@ -40,6 +40,9 @@ Thank you everybody for your generous contributions!
* Beliar
* Robert Iadanza
* SleepyMode
* Marko Viitanen
* David R Miller
* Sven-Bertil Blom

## Mini Backers

Expand Down
10 changes: 10 additions & 0 deletions sources/assets/Xenko.Core.Assets/Analysis/BuildAssetNode.cs
Expand Up @@ -93,6 +93,11 @@ public override int GetHashCode()
}
}

public override string ToString()
{
return $"{DependencyType}: {Source} => {Target}";
}

/// <inheritdoc/>
public static bool operator ==(BuildAssetLink left, BuildAssetLink right)
{
Expand Down Expand Up @@ -235,6 +240,11 @@ private void AddDependencies(AssetItem assetItem, HashSet<BuildDependencyInfo> t
}
}

public override string ToString()
{
return $"{AssetItem.Location} ({References.Count} refs)";
}

private class RuntimeDependenciesCollector : AssetVisitorBase
{
private object visitedRuntimeObject;
Expand Down
2 changes: 1 addition & 1 deletion sources/assets/Xenko.Core.Assets/AssetItem.cs
Expand Up @@ -229,7 +229,7 @@ public bool IsDirty

public override string ToString()
{
return $"[{Asset.GetType().Name}] {location} => {Id}";
return $"[{Asset.GetType().Name}] {location}";
}

/// <summary>
Expand Down
Expand Up @@ -6,6 +6,10 @@
using Xenko.Core.Assets.Analysis;
using Xenko.Core.BuildEngine;
using Xenko.Core.Annotations;
using System.Threading.Tasks;
using Xenko.Core.Diagnostics;
using Xenko.Core.Extensions;
using System.Linq;

namespace Xenko.Core.Assets.Compiler
{
Expand Down Expand Up @@ -85,19 +89,21 @@ public AssetCompilerResult Prepare(AssetCompilerContext context, AssetItem asset

if ((dependencyType & BuildDependencyType.Runtime) == BuildDependencyType.Runtime && compilerResult.HasErrors) //allow Runtime dependencies to fail
{
//totally skip this asset but do not propagate errors!
return;
assetBuildSteps = new ErrorBuildStep(assetItem, compilerResult.Messages);
}
else
{

assetBuildSteps = compilerResult.BuildSteps;
compiledItems.Add(assetNode.AssetItem.Id, assetBuildSteps);
assetBuildSteps = compilerResult.BuildSteps;
compiledItems.Add(assetNode.AssetItem.Id, assetBuildSteps);

// Copy the log to the final result (note: this does not copy or forward the build steps)
compilerResult.CopyTo(finalResult);
if (compilerResult.HasErrors)
{
finalResult.Error($"Failed to prepare asset {assetItem.Location}");
return;
// Copy the log to the final result (note: this does not copy or forward the build steps)
compilerResult.CopyTo(finalResult);
if (compilerResult.HasErrors)
{
finalResult.Error($"Failed to prepare asset {assetItem.Location}");
return;
}
}

// Add the resulting build steps to the final
Expand Down Expand Up @@ -126,5 +132,23 @@ public AssetCompilerResult Prepare(AssetCompilerContext context, AssetItem asset
if (parentBuildStep != null && assetBuildSteps != null && (dependencyType & BuildDependencyType.CompileContent) == BuildDependencyType.CompileContent) //only if content is required Content.Load
BuildStep.LinkBuildSteps(assetBuildSteps, parentBuildStep);
}

private class ErrorBuildStep : AssetBuildStep
{
private readonly List<ILogMessage> messages;

public ErrorBuildStep(AssetItem assetItem, IEnumerable<ILogMessage> messages)
: base(assetItem)
{
this.messages = messages.ToList();
}

public override Task<ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
{
foreach (var message in messages)
executeContext.Logger.Log(message);
return Task.FromResult(ResultStatus.Failed);
}
}
}
}
9 changes: 6 additions & 3 deletions sources/engine/Xenko.Assets/Media/SoundAssetCompiler.cs
Expand Up @@ -34,6 +34,7 @@ protected class DecodeSoundFileCommand : AssetCommand<SoundAsset>
public DecodeSoundFileCommand(string url, SoundAsset parameters, IAssetFinder assetFinder)
: base(url, parameters, assetFinder)
{
Version = 1;
}

/// <inheritdoc />
Expand Down Expand Up @@ -98,11 +99,12 @@ protected override async Task<ResultStatus> DoCommandOverride(ICommandContext co
writer.Write((short)len);
outputStream.Write(outputBuffer, 0, len);

count = 0;
Array.Clear(buffer, 0, frameSize);

newSound.Samples += count / channels;
newSound.NumberOfPackets++;
newSound.MaxPacketLength = Math.Max(newSound.MaxPacketLength, len);

count = 0;
Array.Clear(buffer, 0, frameSize);
}

buffer[count] = reader.ReadSingle();
Expand All @@ -115,6 +117,7 @@ protected override async Task<ResultStatus> DoCommandOverride(ICommandContext co
writer.Write((short)len);
outputStream.Write(outputBuffer, 0, len);

newSound.Samples += count / channels;
newSound.NumberOfPackets++;
newSound.MaxPacketLength = Math.Max(newSound.MaxPacketLength, len);
}
Expand Down
53 changes: 31 additions & 22 deletions sources/engine/Xenko.Audio/CompressedSoundSource.cs
Expand Up @@ -39,6 +39,7 @@ internal sealed class CompressedSoundSource : DynamicSoundSource

private readonly int channels;
private readonly int sampleRate;
private readonly int samples;

private readonly int maxCompressedSize;
private byte[] compressedBuffer;
Expand All @@ -50,7 +51,7 @@ internal sealed class CompressedSoundSource : DynamicSoundSource
private byte[] byteBuffer = null;
private int byteBufferCurrentPosition = 0;

public CompressedSoundSource(SoundInstance instance, byte[] byteBuffer, int numberOfPackets, int sampleRate, int channels, int maxCompressedSize)
public CompressedSoundSource(SoundInstance instance, byte[] byteBuffer, int numberOfPackets, int numberOfSamples, int sampleRate, int channels, int maxCompressedSize)
: base(instance, NumberOfBuffers, SamplesPerBuffer * MaxChannels * sizeof(short))
{
looped = instance.IsLooping;
Expand All @@ -60,6 +61,7 @@ public CompressedSoundSource(SoundInstance instance, byte[] byteBuffer, int numb
this.byteBuffer = byteBuffer;
this.sampleRate = sampleRate;
this.numberOfPackets = numberOfPackets;
this.samples = numberOfSamples;
playRange = new PlayRange(TimeSpan.Zero, TimeSpan.Zero);

NewSources.Add(this);
Expand All @@ -78,7 +80,7 @@ public CompressedSoundSource(SoundInstance instance, byte[] byteBuffer, int numb
/// <param name="sampleRate">The sample rate of the compressed data</param>
/// <param name="channels">The number of channels of the compressed data</param>
/// <param name="maxCompressedSize">The maximum size of a compressed packet</param>
public CompressedSoundSource(SoundInstance instance, IVirtualFileProvider fileProvider, string soundStreamUrl, int numberOfPackets, int sampleRate, int channels, int maxCompressedSize)
public CompressedSoundSource(SoundInstance instance, IVirtualFileProvider fileProvider, string soundStreamUrl, int numberOfPackets, int numberOfSamples, int sampleRate, int channels, int maxCompressedSize)
: base(instance, NumberOfBuffers, SamplesPerBuffer * MaxChannels * sizeof(short))
{
looped = instance.IsLooping;
Expand All @@ -88,6 +90,7 @@ public CompressedSoundSource(SoundInstance instance, IVirtualFileProvider filePr
this.soundStreamUrl = soundStreamUrl;
this.sampleRate = sampleRate;
this.numberOfPackets = numberOfPackets;
this.samples = numberOfSamples;
playRange = new PlayRange(TimeSpan.Zero, TimeSpan.Zero);

NewSources.Add(this);
Expand Down Expand Up @@ -153,30 +156,36 @@ protected override void PrepareInternal()
range = playRange;
}

if (range.Start != TimeSpan.Zero || range.Length != TimeSpan.Zero)
{
var frameSize = SamplesPerFrame * channels;
//ok we need to handle this case properly, this means that the user wants to use a different then full audio stream range...
var sampleStart = sampleRate * (double)channels * range.Start.TotalSeconds;
startPktSampleIndex = (int)Math.Floor(sampleStart) % (frameSize);
// Reset decoder state
decoder.ResetDecoder();

// Ignore invalid data at beginning (due to encoder delay) & end of stream (due to packet size)
var samplesToSkip = decoder.GetDecoderSampleDelay();

var sampleStop = sampleRate * (double)channels * range.End.TotalSeconds;
endPktSampleIndex = frameSize - (int)Math.Floor(sampleStart) % frameSize;
var frameSize = SamplesPerFrame * channels;
//ok we need to handle this case properly, this means that the user wants to use a different then full audio stream range...
var sampleStart = (channels * samplesToSkip) + (int)Math.Floor(sampleRate * (double)channels * range.Start.TotalSeconds);
startPktSampleIndex = sampleStart % (frameSize);

var skipCounter = startingPacketIndex = (int)Math.Floor(sampleStart / frameSize);
endPacketIndex = (int)Math.Floor(sampleStop / frameSize);
var sampleStop = (channels * samplesToSkip)
+ (range.Length != TimeSpan.Zero
? (int)Math.Floor(sampleRate * (double)channels * range.End.TotalSeconds)
: (channels * samples));
endPktSampleIndex = frameSize - sampleStop % frameSize;

// skip to the starting packet
if (startingPacketIndex < numberOfPackets && endPacketIndex < numberOfPackets && startingPacketIndex < endPacketIndex)
var skipCounter = startingPacketIndex = sampleStart / frameSize;
endPacketIndex = sampleStop / frameSize;

// skip to the starting packet
if (startingPacketIndex < numberOfPackets && endPacketIndex < numberOfPackets && startingPacketIndex < endPacketIndex)
{
//valid offsets.. process it
while (skipCounter-- > 0)
{
//valid offsets.. process it
while (skipCounter-- > 0)
{
//skip data to reach starting packet
var len = reader.ReadInt16();
compressedSoundStream.Position = compressedSoundStream.Position + len;
currentPacketIndex++;
}
//skip data to reach starting packet
var len = reader.ReadInt16();
compressedSoundStream.Position = compressedSoundStream.Position + len;
currentPacketIndex++;
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions sources/engine/Xenko.Audio/Native/Celt.cpp
Expand Up @@ -46,6 +46,16 @@ extern "C" {
delete celt;
}

DLL_EXPORT_API void xnCeltResetDecoder(XenkoCelt* celt)
{
opus_custom_decoder_ctl(celt->GetDecoder(), OPUS_RESET_STATE);
}

DLL_EXPORT_API int xnCeltGetDecoderSampleDelay(XenkoCelt* celt, int32_t* delay)
{
return opus_custom_decoder_ctl(celt->GetDecoder(), OPUS_GET_LOOKAHEAD(delay));
}

DLL_EXPORT_API int xnCeltEncodeFloat(XenkoCelt* celt, float* inputSamples, int numberOfInputSamples, uint8_t* outputBuffer, int maxOutputSize)
{
return opus_custom_encode_float(celt->GetEncoder(), inputSamples, numberOfInputSamples, outputBuffer, maxOutputSize);
Expand Down
28 changes: 28 additions & 0 deletions sources/engine/Xenko.Audio/Native/Celt.cs
Expand Up @@ -88,6 +88,26 @@ public unsafe int Decode(byte[] inputBuffer, int inputBufferSize, short* outputS
}
}

/// <summary>
/// Reset decoder state.
/// </summary>
public void ResetDecoder()
{
xnCeltResetDecoder(celtPtr);
}

/// <summary>
/// Gets the delay between encoder and decoder (in number of samples). This should be skipped at the beginning of a decoded stream.
/// </summary>
/// <returns></returns>
public int GetDecoderSampleDelay()
{
var delay = 0;
if (xnCeltGetDecoderSampleDelay(celtPtr, ref delay) != 0)
delay = 0;
return delay;
}

/// <summary>
/// Encode PCM audio into celt compressed format
/// </summary>
Expand Down Expand Up @@ -142,6 +162,14 @@ public unsafe int Encode(float[] audioSamples, byte[] outputBuffer)
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern void xnCeltDestroy(IntPtr celt);

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern int xnCeltResetDecoder(IntPtr celt);

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern int xnCeltGetDecoderSampleDelay(IntPtr celt, ref int delay);

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern unsafe int xnCeltEncodeFloat(IntPtr celt, float* inputSamples, int numberOfInputSamples, byte* outputBuffer, int maxOutputSize);
Expand Down
6 changes: 5 additions & 1 deletion sources/engine/Xenko.Audio/Sound.cs
Expand Up @@ -31,6 +31,8 @@ public sealed class Sound : SoundBase

internal IVirtualFileProvider FileProvider;

internal int Samples { get; set; }

/// <summary>
/// Create a new sound effect instance of the sound effect.
/// The audio data are shared between the instances so that useless memory copies is avoided.
Expand Down Expand Up @@ -96,7 +98,9 @@ internal void LoadSoundInMemory()
offset += samplesDecoded * Channels * sizeof(short);
}

AudioLayer.BufferFill(PreloadedBuffer, memory.Pointer, memory.Length * sizeof(short), SampleRate, Channels == 1);
// Ignore invalid data at beginning (due to encoder delay) & end of stream (due to packet size)
var samplesToSkip = decoder.GetDecoderSampleDelay();
AudioLayer.BufferFill(PreloadedBuffer, memory.Pointer + samplesToSkip * Channels * sizeof(short), Samples * Channels * sizeof(short), SampleRate, Channels == 1);
memory.Dispose();
}
}
Expand Down
2 changes: 1 addition & 1 deletion sources/engine/Xenko.Audio/SoundInstance.cs
Expand Up @@ -81,7 +81,7 @@ internal SoundInstance(Sound staticSound, AudioListener listener, bool forceLoad

if (streamed)
{
soundSource = new CompressedSoundSource(this, staticSound.FileProvider, staticSound.CompressedDataUrl, staticSound.NumberOfPackets, staticSound.SampleRate, staticSound.Channels, staticSound.MaxPacketLength);
soundSource = new CompressedSoundSource(this, staticSound.FileProvider, staticSound.CompressedDataUrl, staticSound.NumberOfPackets, staticSound.Samples, staticSound.SampleRate, staticSound.Channels, staticSound.MaxPacketLength);
}
else
{
Expand Down
2 changes: 2 additions & 0 deletions sources/engine/Xenko.Audio/SoundSerializer.cs
Expand Up @@ -27,6 +27,7 @@ public override void Serialize(ref Sound obj, ArchiveMode mode, SerializationStr
obj.Spatialized = stream.ReadBoolean();
obj.NumberOfPackets = stream.ReadInt16();
obj.MaxPacketLength = stream.ReadInt16();
obj.Samples = stream.ReadInt32();

if (!obj.StreamFromDisk && audioEngine != null && audioEngine.State != AudioEngineState.Invalidated && audioEngine.State != AudioEngineState.Disposed) //immediatelly preload all the data and decode
{
Expand All @@ -47,6 +48,7 @@ public override void Serialize(ref Sound obj, ArchiveMode mode, SerializationStr
stream.Write(obj.Spatialized);
stream.Write((short)obj.NumberOfPackets);
stream.Write((short)obj.MaxPacketLength);
stream.Write(obj.Samples);
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions sources/engine/Xenko.Graphics/Buffer.Vertex.cs
Expand Up @@ -38,10 +38,13 @@ public static class Vertex
/// <param name="device">The <see cref="GraphicsDevice"/>.</param>
/// <param name="size">The size in bytes.</param>
/// <param name="usage">The usage.</param>
/// <returns>A Vertex buffer</returns>
public static Buffer New(GraphicsDevice device, int size, GraphicsResourceUsage usage = GraphicsResourceUsage.Default)
/// <param name="bindFlags">The bind flags, can be combined with <see cref="BufferFlags.StreamOutput"/> to use the buffer as a stream output target.</param>
/// <returns>
/// A Vertex buffer
/// </returns>
public static Buffer New(GraphicsDevice device, int size, GraphicsResourceUsage usage = GraphicsResourceUsage.Default, BufferFlags bindFlags = BufferFlags.VertexBuffer)
{
return Buffer.New(device, size, BufferFlags.VertexBuffer, usage);
return Buffer.New(device, size, bindFlags, usage);
}

/// <summary>
Expand Down
5 changes: 5 additions & 0 deletions sources/engine/Xenko.Graphics/BufferFlags.cs
Expand Up @@ -71,5 +71,10 @@ public enum BufferFlags
/// Creates an indirect arguments buffer.
/// </summary>
ArgumentBuffer = 1024,

/// <summary>
/// Creates a buffer for the geometry shader stream-output stage.
/// </summary>
StreamOutput = 2048,
}
}
3 changes: 3 additions & 0 deletions sources/engine/Xenko.Graphics/Direct3D/Buffer.Direct3D.cs
Expand Up @@ -240,6 +240,9 @@ private static SharpDX.Direct3D11.BufferDescription ConvertToNativeDescription(B
if ((bufferFlags & BufferFlags.ArgumentBuffer) == BufferFlags.ArgumentBuffer)
desc.OptionFlags |= ResourceOptionFlags.DrawIndirectArguments;

if ((bufferFlags & BufferFlags.StreamOutput) != 0)
desc.BindFlags |= BindFlags.StreamOutput;

return desc;
}

Expand Down

0 comments on commit be8bb7d

Please sign in to comment.