156 lines
7.2 KiB
C#
156 lines
7.2 KiB
C#
using System.Collections.Generic;
|
|
using SharpDX.Direct3D;
|
|
using TwoMGFX.TPGParser;
|
|
|
|
namespace TwoMGFX
|
|
{
|
|
internal partial class ShaderData
|
|
{
|
|
public static ShaderData CreateHLSL(byte[] byteCode, bool isVertexShader, List<ConstantBufferData> cbuffers, int sharedIndex, Dictionary<string, SamplerStateInfo> samplerStates, bool debug)
|
|
{
|
|
var dxshader = new ShaderData(isVertexShader, sharedIndex, byteCode);
|
|
dxshader._attributes = new Attribute[0];
|
|
|
|
// Strip the bytecode we're gonna save!
|
|
var stripFlags = SharpDX.D3DCompiler.StripFlags.CompilerStripReflectionData |
|
|
SharpDX.D3DCompiler.StripFlags.CompilerStripTestBlobs;
|
|
|
|
if (!debug)
|
|
stripFlags |= SharpDX.D3DCompiler.StripFlags.CompilerStripDebugInformation;
|
|
|
|
using (var original = new SharpDX.D3DCompiler.ShaderBytecode(byteCode))
|
|
{
|
|
// Strip the bytecode for saving to disk.
|
|
var stripped = original.Strip(stripFlags);
|
|
{
|
|
// Only SM4 and above works with strip... so this can return null!
|
|
if (stripped != null)
|
|
{
|
|
dxshader.ShaderCode = stripped;
|
|
}
|
|
else
|
|
{
|
|
// TODO: There is a way to strip SM3 and below
|
|
// but we have to write the method ourselves.
|
|
//
|
|
// If we need to support it then consider porting
|
|
// this code over...
|
|
//
|
|
// http://entland.homelinux.com/blog/2009/01/15/stripping-comments-from-shader-bytecodes/
|
|
//
|
|
dxshader.ShaderCode = (byte[])dxshader.Bytecode.Clone();
|
|
}
|
|
}
|
|
|
|
// Use reflection to get details of the shader.
|
|
using (var refelect = new SharpDX.D3DCompiler.ShaderReflection(byteCode))
|
|
{
|
|
// Get the samplers.
|
|
var samplers = new List<Sampler>();
|
|
for (var i = 0; i < refelect.Description.BoundResources; i++)
|
|
{
|
|
var rdesc = refelect.GetResourceBindingDescription(i);
|
|
if (rdesc.Type == SharpDX.D3DCompiler.ShaderInputType.Texture)
|
|
{
|
|
var samplerName = rdesc.Name;
|
|
|
|
var sampler = new Sampler
|
|
{
|
|
samplerName = string.Empty,
|
|
textureSlot = rdesc.BindPoint,
|
|
samplerSlot = rdesc.BindPoint,
|
|
parameterName = samplerName
|
|
};
|
|
|
|
SamplerStateInfo state;
|
|
if (samplerStates.TryGetValue(samplerName, out state))
|
|
{
|
|
sampler.parameterName = state.TextureName ?? samplerName;
|
|
sampler.state = state.State;
|
|
}
|
|
else
|
|
{
|
|
foreach (var s in samplerStates.Values)
|
|
{
|
|
if (samplerName == s.TextureName)
|
|
{
|
|
sampler.state = s.State;
|
|
samplerName = s.Name;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Find sampler slot, which can be different from the texture slot.
|
|
for (int j = 0; j < refelect.Description.BoundResources; j++)
|
|
{
|
|
var samplerrdesc = refelect.GetResourceBindingDescription(j);
|
|
|
|
if (samplerrdesc.Type == SharpDX.D3DCompiler.ShaderInputType.Sampler &&
|
|
samplerrdesc.Name == samplerName)
|
|
{
|
|
sampler.samplerSlot = samplerrdesc.BindPoint;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (rdesc.Dimension)
|
|
{
|
|
case ShaderResourceViewDimension.Texture1D:
|
|
case ShaderResourceViewDimension.Texture1DArray:
|
|
sampler.type = MojoShader.MOJOSHADER_samplerType.MOJOSHADER_SAMPLER_1D;
|
|
break;
|
|
|
|
case ShaderResourceViewDimension.Texture2D:
|
|
case ShaderResourceViewDimension.Texture2DArray:
|
|
case ShaderResourceViewDimension.Texture2DMultisampled:
|
|
case ShaderResourceViewDimension.Texture2DMultisampledArray:
|
|
sampler.type = MojoShader.MOJOSHADER_samplerType.MOJOSHADER_SAMPLER_2D;
|
|
break;
|
|
|
|
case ShaderResourceViewDimension.Texture3D:
|
|
sampler.type = MojoShader.MOJOSHADER_samplerType.MOJOSHADER_SAMPLER_VOLUME;
|
|
break;
|
|
|
|
case ShaderResourceViewDimension.TextureCube:
|
|
case ShaderResourceViewDimension.TextureCubeArray:
|
|
sampler.type = MojoShader.MOJOSHADER_samplerType.MOJOSHADER_SAMPLER_CUBE;
|
|
break;
|
|
}
|
|
|
|
samplers.Add(sampler);
|
|
}
|
|
}
|
|
dxshader._samplers = samplers.ToArray();
|
|
|
|
// Gather all the constant buffers used by this shader.
|
|
dxshader._cbuffers = new int[refelect.Description.ConstantBuffers];
|
|
for (var i = 0; i < refelect.Description.ConstantBuffers; i++)
|
|
{
|
|
var cb = new ConstantBufferData(refelect.GetConstantBuffer(i));
|
|
|
|
// Look for a duplicate cbuffer in the list.
|
|
for (var c = 0; c < cbuffers.Count; c++)
|
|
{
|
|
if (cb.SameAs(cbuffers[c]))
|
|
{
|
|
cb = null;
|
|
dxshader._cbuffers[i] = c;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Add a new cbuffer.
|
|
if (cb != null)
|
|
{
|
|
dxshader._cbuffers[i] = cbuffers.Count;
|
|
cbuffers.Add(cb);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return dxshader;
|
|
}
|
|
}
|
|
} |