diff --git a/internal/graphicsdriver/directx/graphics11_windows.go b/internal/graphicsdriver/directx/graphics11_windows.go index 6a111edbf..4d91d703f 100644 --- a/internal/graphicsdriver/directx/graphics11_windows.go +++ b/internal/graphicsdriver/directx/graphics11_windows.go @@ -27,34 +27,56 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/shaderir/hlsl" ) -var inputElementDescsForDX11 = []_D3D11_INPUT_ELEMENT_DESC{ - { - SemanticName: &([]byte("POSITION\000"))[0], - SemanticIndex: 0, - Format: _DXGI_FORMAT_R32G32_FLOAT, - InputSlot: 0, - AlignedByteOffset: _D3D11_APPEND_ALIGNED_ELEMENT, - InputSlotClass: _D3D11_INPUT_PER_VERTEX_DATA, - InstanceDataStepRate: 0, - }, - { - SemanticName: &([]byte("TEXCOORD\000"))[0], - SemanticIndex: 0, - Format: _DXGI_FORMAT_R32G32_FLOAT, - InputSlot: 0, - AlignedByteOffset: _D3D11_APPEND_ALIGNED_ELEMENT, - InputSlotClass: _D3D11_INPUT_PER_VERTEX_DATA, - InstanceDataStepRate: 0, - }, - { - SemanticName: &([]byte("COLOR\000"))[0], - SemanticIndex: 0, - Format: _DXGI_FORMAT_R32G32B32A32_FLOAT, - InputSlot: 0, - AlignedByteOffset: _D3D11_APPEND_ALIGNED_ELEMENT, - InputSlotClass: _D3D11_INPUT_PER_VERTEX_DATA, - InstanceDataStepRate: 0, - }, +var inputElementDescsForDX11 []_D3D11_INPUT_ELEMENT_DESC + +func init() { + inputElementDescsForDX11 = []_D3D11_INPUT_ELEMENT_DESC{ + { + SemanticName: &([]byte("POSITION\000"))[0], + SemanticIndex: 0, + Format: _DXGI_FORMAT_R32G32_FLOAT, + InputSlot: 0, + AlignedByteOffset: _D3D11_APPEND_ALIGNED_ELEMENT, + InputSlotClass: _D3D11_INPUT_PER_VERTEX_DATA, + InstanceDataStepRate: 0, + }, + { + SemanticName: &([]byte("TEXCOORD\000"))[0], + SemanticIndex: 0, + Format: _DXGI_FORMAT_R32G32_FLOAT, + InputSlot: 0, + AlignedByteOffset: _D3D11_APPEND_ALIGNED_ELEMENT, + InputSlotClass: _D3D11_INPUT_PER_VERTEX_DATA, + InstanceDataStepRate: 0, + }, + { + SemanticName: &([]byte("COLOR\000"))[0], + SemanticIndex: 0, + Format: _DXGI_FORMAT_R32G32B32A32_FLOAT, + InputSlot: 0, + AlignedByteOffset: _D3D11_APPEND_ALIGNED_ELEMENT, + InputSlotClass: _D3D11_INPUT_PER_VERTEX_DATA, + InstanceDataStepRate: 0, + }, + } + diff := graphics.VertexFloatCount - 8 + if diff == 0 { + return + } + if diff%4 != 0 { + panic("directx: unexpected attribute layout") + } + for i := 0; i < diff/4; i++ { + inputElementDescsForDX11 = append(inputElementDescsForDX11, _D3D11_INPUT_ELEMENT_DESC{ + SemanticName: &([]byte("COLOR\000"))[0], + SemanticIndex: uint32(i) + 1, + Format: _DXGI_FORMAT_R32G32B32A32_FLOAT, + InputSlot: 0, + AlignedByteOffset: _D3D11_APPEND_ALIGNED_ELEMENT, + InputSlotClass: _D3D11_INPUT_PER_VERTEX_DATA, + InstanceDataStepRate: 0, + }) + } } func blendFactorToBlend11(f graphicsdriver.BlendFactor, alpha bool) _D3D11_BLEND { diff --git a/internal/graphicsdriver/directx/pipeline12_windows.go b/internal/graphicsdriver/directx/pipeline12_windows.go index 819454786..ce666ee42 100644 --- a/internal/graphicsdriver/directx/pipeline12_windows.go +++ b/internal/graphicsdriver/directx/pipeline12_windows.go @@ -23,34 +23,56 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" ) -var inputElementDescsForDX12 = []_D3D12_INPUT_ELEMENT_DESC{ - { - SemanticName: &([]byte("POSITION\000"))[0], - SemanticIndex: 0, - Format: _DXGI_FORMAT_R32G32_FLOAT, - InputSlot: 0, - AlignedByteOffset: _D3D12_APPEND_ALIGNED_ELEMENT, - InputSlotClass: _D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, - InstanceDataStepRate: 0, - }, - { - SemanticName: &([]byte("TEXCOORD\000"))[0], - SemanticIndex: 0, - Format: _DXGI_FORMAT_R32G32_FLOAT, - InputSlot: 0, - AlignedByteOffset: _D3D12_APPEND_ALIGNED_ELEMENT, - InputSlotClass: _D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, - InstanceDataStepRate: 0, - }, - { - SemanticName: &([]byte("COLOR\000"))[0], - SemanticIndex: 0, - Format: _DXGI_FORMAT_R32G32B32A32_FLOAT, - InputSlot: 0, - AlignedByteOffset: _D3D12_APPEND_ALIGNED_ELEMENT, - InputSlotClass: _D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, - InstanceDataStepRate: 0, - }, +var inputElementDescsForDX12 []_D3D12_INPUT_ELEMENT_DESC + +func init() { + inputElementDescsForDX12 = []_D3D12_INPUT_ELEMENT_DESC{ + { + SemanticName: &([]byte("POSITION\000"))[0], + SemanticIndex: 0, + Format: _DXGI_FORMAT_R32G32_FLOAT, + InputSlot: 0, + AlignedByteOffset: _D3D12_APPEND_ALIGNED_ELEMENT, + InputSlotClass: _D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, + InstanceDataStepRate: 0, + }, + { + SemanticName: &([]byte("TEXCOORD\000"))[0], + SemanticIndex: 0, + Format: _DXGI_FORMAT_R32G32_FLOAT, + InputSlot: 0, + AlignedByteOffset: _D3D12_APPEND_ALIGNED_ELEMENT, + InputSlotClass: _D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, + InstanceDataStepRate: 0, + }, + { + SemanticName: &([]byte("COLOR\000"))[0], + SemanticIndex: 0, + Format: _DXGI_FORMAT_R32G32B32A32_FLOAT, + InputSlot: 0, + AlignedByteOffset: _D3D12_APPEND_ALIGNED_ELEMENT, + InputSlotClass: _D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, + InstanceDataStepRate: 0, + }, + } + diff := graphics.VertexFloatCount - 8 + if diff == 0 { + return + } + if diff%4 != 0 { + panic("directx: unexpected attribute layout") + } + for i := 0; i < diff/4; i++ { + inputElementDescsForDX12 = append(inputElementDescsForDX12, _D3D12_INPUT_ELEMENT_DESC{ + SemanticName: &([]byte("COLOR\000"))[0], + SemanticIndex: uint32(i) + 1, + Format: _DXGI_FORMAT_R32G32B32A32_FLOAT, + InputSlot: 0, + AlignedByteOffset: _D3D12_APPEND_ALIGNED_ELEMENT, + InputSlotClass: _D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, + InstanceDataStepRate: 0, + }) + } } const numDescriptorsPerFrame = 32 diff --git a/internal/shaderir/hlsl/hlsl.go b/internal/shaderir/hlsl/hlsl.go index 22a05e635..d1e558407 100644 --- a/internal/shaderir/hlsl/hlsl.go +++ b/internal/shaderir/hlsl/hlsl.go @@ -52,13 +52,7 @@ func (c *compileContext) structName(p *shaderir.Program, t *shaderir.Type) strin return n } -const Prelude = `struct Varyings { - float4 Position : SV_POSITION; - float2 M0 : TEXCOORD0; - float4 M1 : COLOR; -}; - -float mod(float x, float y) { +const Prelude = `float mod(float x, float y) { return x - y * floor(x/y); } @@ -95,6 +89,27 @@ func Compile(p *shaderir.Program) (vertexShader, pixelShader string) { var lines []string lines = append(lines, strings.Split(Prelude, "\n")...) + + lines = append(lines, "", "struct Varyings {") + lines = append(lines, "\tfloat4 Position : SV_POSITION;") + if len(p.Varyings) > 0 { + for i, v := range p.Varyings { + switch i { + case 0: + lines = append(lines, fmt.Sprintf("\tfloat2 M%d : TEXCOORD0;", i)) + case 1: + lines = append(lines, fmt.Sprintf("\tfloat4 M%d : COLOR0;", i)) + default: + // Use COLOR[n] as a general purpose varying. + if v.Main != shaderir.Vec4 { + lines = append(lines, fmt.Sprintf("\t?(unexpected type: %s) M%d : COLOR%d;", v, i, i-1)) + } else { + lines = append(lines, fmt.Sprintf("\tfloat4 M%d : COLOR%d;", i, i-1)) + } + } + } + } + lines = append(lines, "};") lines = append(lines, "", "{{.Structs}}") if len(p.Uniforms) > 0 { @@ -156,7 +171,25 @@ func Compile(p *shaderir.Program) (vertexShader, pixelShader string) { } if p.VertexFunc.Block != nil && len(p.VertexFunc.Block.Stmts) > 0 { vslines = append(vslines, "") - vslines = append(vslines, "Varyings VSMain(float2 A0 : POSITION, float2 A1 : TEXCOORD, float4 A2 : COLOR) {") + var args []string + for i, a := range p.Attributes { + switch i { + case 0: + args = append(args, fmt.Sprintf("float2 A%d : POSITION", i)) + case 1: + args = append(args, fmt.Sprintf("float2 A%d : TEXCOORD0", i)) + case 2: + args = append(args, fmt.Sprintf("float4 A%d : COLOR0", i)) + default: + // Use COLOR[n] as a general purpose varying. + if a.Main != shaderir.Vec4 { + args = append(args, fmt.Sprintf("?(unexpected type: %s) A%d : COLOR%d", a, i, i-2)) + } else { + args = append(args, fmt.Sprintf("float4 A%d : COLOR%d", i, i-2)) + } + } + } + vslines = append(vslines, "Varyings VSMain("+strings.Join(args, ", ")+") {") vslines = append(vslines, fmt.Sprintf("\tVaryings %s;", vsOut)) vslines = append(vslines, c.block(p, p.VertexFunc.Block, p.VertexFunc.Block, 0)...) if last := fmt.Sprintf("\treturn %s;", vsOut); vslines[len(vslines)-1] != last {