From 1d3a9fb2d6c1142da497f56a577b54feda288a09 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Fri, 28 Feb 2020 15:10:17 +0100 Subject: [PATCH] internal/cmd/convertshaders: replace fxc.exe with D3DCompile D3DCompile successfully compiles shaders fxc.exe doesn't. As a bonus the DirectX SDK is no longer required (it includes fxc.exe). Signed-off-by: Elias Naur --- app/internal/d3d11/d3d11_windows.go | 77 -------------- internal/cmd/convertshaders/hlsl_noop.go | 9 ++ internal/cmd/convertshaders/hlsl_windows.go | 9 ++ internal/cmd/convertshaders/main.go | 30 +----- internal/d3dcompile/compile_windows.go | 107 ++++++++++++++++++++ 5 files changed, 128 insertions(+), 104 deletions(-) create mode 100644 internal/cmd/convertshaders/hlsl_noop.go create mode 100644 internal/cmd/convertshaders/hlsl_windows.go create mode 100644 internal/d3dcompile/compile_windows.go diff --git a/app/internal/d3d11/d3d11_windows.go b/app/internal/d3d11/d3d11_windows.go index 6a4dfcd9..a12750c9 100644 --- a/app/internal/d3d11/d3d11_windows.go +++ b/app/internal/d3d11/d3d11_windows.go @@ -9,8 +9,6 @@ import ( "syscall" - gunsafe "gioui.org/internal/unsafe" - "golang.org/x/sys/windows" ) @@ -360,14 +358,6 @@ type _ID3D11InputLayout struct { } } -type _ID3DBlob struct { - vtbl *struct { - _IUnknownVTbl - GetBufferPointer uintptr - GetBufferSize uintptr - } -} - type _D3D11_DEPTH_STENCIL_DESC struct { DepthEnable uint32 DepthWriteMask uint32 @@ -560,10 +550,6 @@ var ( __D3D11CreateDevice = d3d11.NewProc("D3D11CreateDevice") __D3D11CreateDeviceAndSwapChain = d3d11.NewProc("D3D11CreateDeviceAndSwapChain") - - d3dcompiler_47 = windows.NewLazySystemDLL("d3dcompiler_47.dll") - - __D3DCompile = d3dcompiler_47.NewProc("D3DCompile") ) const ( @@ -699,41 +685,6 @@ func _D3D11CreateDeviceAndSwapChain(driverType uint32, flags uint32, swapDesc *_ return dev, ctx, swchain, featLvl, nil } -func _D3DCompile(src []byte, entryPoint, target string) ([]byte, error) { - var ( - code *_ID3DBlob - errors *_ID3DBlob - ) - entryPoint0 := []byte(entryPoint + "\x00") - target0 := []byte(target + "\x00") - r, _, _ := __D3DCompile.Call( - uintptr(unsafe.Pointer(&src[0])), - uintptr(len(src)), - 0, // pSourceName - 0, // pDefines - 0, // pInclude - uintptr(unsafe.Pointer(&entryPoint0[0])), - uintptr(unsafe.Pointer(&target0[0])), - 0, // Flags1 - 0, // Flags2 - uintptr(unsafe.Pointer(&code)), - uintptr(unsafe.Pointer(&errors)), - ) - var compileErr string - if errors != nil { - compileErr = string(errors.data()) - _IUnknownRelease(unsafe.Pointer(errors), errors.vtbl.Release) - } - if r != 0 { - return nil, fmt.Errorf("D3D11Compile: %#x: %s", r, compileErr) - } - bytecode := code.data() - cp := make([]byte, len(bytecode)) - copy(cp, bytecode) - _IUnknownRelease(unsafe.Pointer(code), code.vtbl.Release) - return cp, nil -} - func (d *_ID3D11Device) CreateBuffer(desc *_D3D11_BUFFER_DESC, data []byte) (*_ID3D11Buffer, error) { var dataDesc *_D3D11_SUBRESOURCE_DATA if len(data) > 0 { @@ -1281,34 +1232,6 @@ func (c *_ID3D11DeviceContext) OMSetDepthStencilState(state *_ID3D11DepthStencil ) } -func (b *_ID3DBlob) GetBufferPointer() uintptr { - ptr, _, _ := syscall.Syscall( - b.vtbl.GetBufferPointer, - 1, - uintptr(unsafe.Pointer(b)), - 0, - 0, - ) - return ptr -} - -func (b *_ID3DBlob) GetBufferSize() uintptr { - sz, _, _ := syscall.Syscall( - b.vtbl.GetBufferSize, - 1, - uintptr(unsafe.Pointer(b)), - 0, - 0, - ) - return sz -} - -func (b *_ID3DBlob) data() []byte { - data := gunsafe.SliceOf(b.GetBufferPointer()) - n := int(b.GetBufferSize()) - return data[:n:n] -} - func (d *_IDXGIObject) GetParent(guid *_GUID) (*_IDXGIObject, error) { var parent *_IDXGIObject r, _, _ := syscall.Syscall( diff --git a/internal/cmd/convertshaders/hlsl_noop.go b/internal/cmd/convertshaders/hlsl_noop.go new file mode 100644 index 00000000..1e2e6cee --- /dev/null +++ b/internal/cmd/convertshaders/hlsl_noop.go @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +// +build !windows + +package main + +func compileHLSL(src, entry, profile string) ([]byte, error) { + return nil, nil +} diff --git a/internal/cmd/convertshaders/hlsl_windows.go b/internal/cmd/convertshaders/hlsl_windows.go new file mode 100644 index 00000000..ff294269 --- /dev/null +++ b/internal/cmd/convertshaders/hlsl_windows.go @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package main + +import "gioui.org/internal/d3dcompile" + +func compileHLSL(src, entry, profile string) ([]byte, error) { + return d3dcompile.D3DCompile([]byte(src), entry, profile) +} diff --git a/internal/cmd/convertshaders/main.go b/internal/cmd/convertshaders/main.go index 04e50e97..6c417117 100644 --- a/internal/cmd/convertshaders/main.go +++ b/internal/cmd/convertshaders/main.go @@ -55,8 +55,6 @@ func generate() error { if err != nil { return err } - fxc, err := exec.LookPath("fxc") - fxcFound := err == nil shaders, err := filepath.Glob(filepath.Join(absShadersDir, "*")) if err != nil { return err @@ -117,11 +115,9 @@ func generate() error { return fmt.Errorf("unrecognized shader type %s", shader) } var hlslc []byte - if fxcFound { - hlslc, err = compileHLSL(tmp, fxc, hlsl, "main", hlslProf+"_4_0") - if err != nil { - return err - } + hlslc, err = compileHLSL(hlsl, "main", hlslProf+"_4_0") + if err != nil { + return err } // OpenGL 3.2 Core only accepts GLSL version 1.50, but is // otherwise compatible with version 1.30. @@ -310,26 +306,6 @@ func parseDataType(t string) (backend.DataType, int, error) { } } -func compileHLSL(tmp, fxc, src, entry, profile string) ([]byte, error) { - tmpfile := filepath.Join(tmp, "shader.hlsl") - if err := ioutil.WriteFile(tmpfile, []byte(src), 0644); err != nil { - return nil, err - } - outFile := filepath.Join(tmp, "shader.bin") - cmd := exec.Command(fxc, - "/T", profile, - "/E", entry, - "/nologo", - "/Fo", outFile, - tmpfile, - ) - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - return nil, err - } - return ioutil.ReadFile(outFile) -} - func convertShader(tmp, glslcc, path, lang, profile string, args *shaderArgs, flattenUBOs bool) (string, []byte, error) { shaderTmpl, err := template.ParseFiles(path) if err != nil { diff --git a/internal/d3dcompile/compile_windows.go b/internal/d3dcompile/compile_windows.go new file mode 100644 index 00000000..4766be7c --- /dev/null +++ b/internal/d3dcompile/compile_windows.go @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package d3dcompile + +import ( + "fmt" + "unsafe" + + "syscall" + + gunsafe "gioui.org/internal/unsafe" + + "golang.org/x/sys/windows" +) + +var ( + d3dcompiler_47 = windows.NewLazySystemDLL("d3dcompiler_47.dll") + + __D3DCompile = d3dcompiler_47.NewProc("D3DCompile") +) + +type _IUnknownVTbl struct { + QueryInterface uintptr + AddRef uintptr + Release uintptr +} + +type _ID3DBlob struct { + vtbl *struct { + _IUnknownVTbl + GetBufferPointer uintptr + GetBufferSize uintptr + } +} + +func D3DCompile(src []byte, entryPoint, target string) ([]byte, error) { + var ( + code *_ID3DBlob + errors *_ID3DBlob + ) + entryPoint0 := []byte(entryPoint + "\x00") + target0 := []byte(target + "\x00") + r, _, _ := __D3DCompile.Call( + uintptr(unsafe.Pointer(&src[0])), + uintptr(len(src)), + 0, // pSourceName + 0, // pDefines + 0, // pInclude + uintptr(unsafe.Pointer(&entryPoint0[0])), + uintptr(unsafe.Pointer(&target0[0])), + 0, // Flags1 + 0, // Flags2 + uintptr(unsafe.Pointer(&code)), + uintptr(unsafe.Pointer(&errors)), + ) + var compileErr string + if errors != nil { + compileErr = string(errors.data()) + _IUnknownRelease(unsafe.Pointer(errors), errors.vtbl.Release) + } + if r != 0 { + return nil, fmt.Errorf("D3D11Compile: %#x: %s", r, compileErr) + } + bytecode := code.data() + cp := make([]byte, len(bytecode)) + copy(cp, bytecode) + _IUnknownRelease(unsafe.Pointer(code), code.vtbl.Release) + return cp, nil +} + +func (b *_ID3DBlob) GetBufferPointer() uintptr { + ptr, _, _ := syscall.Syscall( + b.vtbl.GetBufferPointer, + 1, + uintptr(unsafe.Pointer(b)), + 0, + 0, + ) + return ptr +} + +func (b *_ID3DBlob) GetBufferSize() uintptr { + sz, _, _ := syscall.Syscall( + b.vtbl.GetBufferSize, + 1, + uintptr(unsafe.Pointer(b)), + 0, + 0, + ) + return sz +} + +func (b *_ID3DBlob) data() []byte { + data := gunsafe.SliceOf(b.GetBufferPointer()) + n := int(b.GetBufferSize()) + return data[:n:n] +} + +func _IUnknownRelease(obj unsafe.Pointer, releaseMethod uintptr) { + syscall.Syscall( + releaseMethod, + 1, + uintptr(obj), + 0, + 0, + ) +}