mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-27 19:22:49 +01:00
internal/shaderir: cache offset calculations for HLSL
This commit is contained in:
parent
c5d664ccf7
commit
4aad9d37e9
@ -24,7 +24,6 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir/hlsl"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var inputElementDescsForDX11 []_D3D11_INPUT_ELEMENT_DESC
|
var inputElementDescsForDX11 []_D3D11_INPUT_ELEMENT_DESC
|
||||||
@ -513,7 +512,7 @@ func (g *graphics11) NewShader(program *shaderir.Program) (graphicsdriver.Shader
|
|||||||
graphics: g,
|
graphics: g,
|
||||||
id: g.genNextShaderID(),
|
id: g.genNextShaderID(),
|
||||||
uniformTypes: program.Uniforms,
|
uniformTypes: program.Uniforms,
|
||||||
uniformOffsets: hlsl.CalcUniformMemoryOffsetsInDWords(program),
|
uniformOffsets: program.UniformOffsetsInDWords(),
|
||||||
vertexShaderBlob: vsh,
|
vertexShaderBlob: vsh,
|
||||||
pixelShaderBlob: psh,
|
pixelShaderBlob: psh,
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/microsoftgdk"
|
"github.com/hajimehoshi/ebiten/v2/internal/microsoftgdk"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir/hlsl"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type resourceWithSize struct {
|
type resourceWithSize struct {
|
||||||
@ -1073,7 +1072,7 @@ func (g *graphics12) NewShader(program *shaderir.Program) (graphicsdriver.Shader
|
|||||||
graphics: g,
|
graphics: g,
|
||||||
id: g.genNextShaderID(),
|
id: g.genNextShaderID(),
|
||||||
uniformTypes: program.Uniforms,
|
uniformTypes: program.Uniforms,
|
||||||
uniformOffsets: hlsl.CalcUniformMemoryOffsetsInDWords(program),
|
uniformOffsets: program.UniformOffsetsInDWords(),
|
||||||
vertexShader: vsh,
|
vertexShader: vsh,
|
||||||
pixelShader: psh,
|
pixelShader: psh,
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ float4x4 float4x4FromScalar(float x) {
|
|||||||
}`
|
}`
|
||||||
|
|
||||||
func Compile(p *shaderir.Program) (vertexShader, pixelShader, prelude string) {
|
func Compile(p *shaderir.Program) (vertexShader, pixelShader, prelude string) {
|
||||||
offsets := CalcUniformMemoryOffsetsInDWords(p)
|
offsets := p.UniformOffsetsInDWords()
|
||||||
|
|
||||||
c := &compileContext{
|
c := &compileContext{
|
||||||
unit: p.Unit,
|
unit: p.Unit,
|
||||||
@ -119,8 +119,8 @@ func Compile(p *shaderir.Program) (vertexShader, pixelShader, prelude string) {
|
|||||||
lines = append(lines, "cbuffer Uniforms : register(b0) {")
|
lines = append(lines, "cbuffer Uniforms : register(b0) {")
|
||||||
for i, t := range p.Uniforms {
|
for i, t := range p.Uniforms {
|
||||||
// packingoffset is not mandatory, but this is useful to ensure the correct offset is used.
|
// packingoffset is not mandatory, but this is useful to ensure the correct offset is used.
|
||||||
offset := fmt.Sprintf("c%d", offsets[i]/boundaryInDWords)
|
offset := fmt.Sprintf("c%d", offsets[i]/shaderir.UniformVariableBoundaryInDWords)
|
||||||
switch offsets[i] % boundaryInDWords {
|
switch offsets[i] % shaderir.UniformVariableBoundaryInDWords {
|
||||||
case 1:
|
case 1:
|
||||||
offset += ".y"
|
offset += ".y"
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -59,7 +59,8 @@ type Program struct {
|
|||||||
|
|
||||||
SourceHash SourceHash
|
SourceHash SourceHash
|
||||||
|
|
||||||
uniformFactors []uint32
|
uniformFactors []uint32
|
||||||
|
offsetsInDWords []int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Func struct {
|
type Func struct {
|
||||||
|
@ -12,89 +12,92 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package hlsl
|
package shaderir
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const boundaryInDWords = 4
|
const UniformVariableBoundaryInDWords = 4
|
||||||
|
|
||||||
|
// UniformOffsetsInDWords returns the offsets of the uniform variables in DWROD units in the HLSL layout.
|
||||||
|
func (p *Program) UniformOffsetsInDWords() []int {
|
||||||
|
if len(p.offsetsInDWords) > 0 {
|
||||||
|
return p.offsetsInDWords
|
||||||
|
}
|
||||||
|
|
||||||
func CalcUniformMemoryOffsetsInDWords(program *shaderir.Program) []int {
|
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules
|
// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules
|
||||||
// https://github.com/microsoft/DirectXShaderCompiler/wiki/Buffer-Packing
|
// https://github.com/microsoft/DirectXShaderCompiler/wiki/Buffer-Packing
|
||||||
|
|
||||||
var offsetsInDWords []int
|
|
||||||
var headInDWords int
|
|
||||||
|
|
||||||
align := func(x int) int {
|
align := func(x int) int {
|
||||||
if x == 0 {
|
if x == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return ((x-1)/boundaryInDWords + 1) * boundaryInDWords
|
return ((x-1)/UniformVariableBoundaryInDWords + 1) * UniformVariableBoundaryInDWords
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var offsetsInDWords []int
|
||||||
|
var headInDWords int
|
||||||
|
|
||||||
// TODO: Reorder the variables with packoffset.
|
// TODO: Reorder the variables with packoffset.
|
||||||
// See https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-variable-packoffset
|
// See https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-variable-packoffset
|
||||||
for _, u := range program.Uniforms {
|
for _, u := range p.Uniforms {
|
||||||
switch u.Main {
|
switch u.Main {
|
||||||
case shaderir.Float:
|
case Float:
|
||||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||||
headInDWords += 1
|
headInDWords += 1
|
||||||
case shaderir.Int:
|
case Int:
|
||||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||||
headInDWords += 1
|
headInDWords += 1
|
||||||
case shaderir.Vec2, shaderir.IVec2:
|
case Vec2, IVec2:
|
||||||
if headInDWords%boundaryInDWords >= 3 {
|
if headInDWords%UniformVariableBoundaryInDWords >= 3 {
|
||||||
headInDWords = align(headInDWords)
|
headInDWords = align(headInDWords)
|
||||||
}
|
}
|
||||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||||
headInDWords += 2
|
headInDWords += 2
|
||||||
case shaderir.Vec3, shaderir.IVec3:
|
case Vec3, IVec3:
|
||||||
if headInDWords%boundaryInDWords >= 2 {
|
if headInDWords%UniformVariableBoundaryInDWords >= 2 {
|
||||||
headInDWords = align(headInDWords)
|
headInDWords = align(headInDWords)
|
||||||
}
|
}
|
||||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||||
headInDWords += 3
|
headInDWords += 3
|
||||||
case shaderir.Vec4, shaderir.IVec4:
|
case Vec4, IVec4:
|
||||||
if headInDWords%boundaryInDWords >= 1 {
|
if headInDWords%UniformVariableBoundaryInDWords >= 1 {
|
||||||
headInDWords = align(headInDWords)
|
headInDWords = align(headInDWords)
|
||||||
}
|
}
|
||||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||||
headInDWords += 4
|
headInDWords += 4
|
||||||
case shaderir.Mat2:
|
case Mat2:
|
||||||
// For matrices, each column is aligned to the boundary.
|
// For matrices, each column is aligned to the boundary.
|
||||||
headInDWords = align(headInDWords)
|
headInDWords = align(headInDWords)
|
||||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||||
headInDWords += 6
|
headInDWords += 6
|
||||||
case shaderir.Mat3:
|
case Mat3:
|
||||||
headInDWords = align(headInDWords)
|
headInDWords = align(headInDWords)
|
||||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||||
headInDWords += 11
|
headInDWords += 11
|
||||||
case shaderir.Mat4:
|
case Mat4:
|
||||||
headInDWords = align(headInDWords)
|
headInDWords = align(headInDWords)
|
||||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||||
headInDWords += 16
|
headInDWords += 16
|
||||||
case shaderir.Array:
|
case Array:
|
||||||
// Each array is 16-byte aligned.
|
// Each array is 16-byte aligned.
|
||||||
// TODO: What if the array has 2 or more dimensions?
|
// TODO: What if the array has 2 or more dimensions?
|
||||||
headInDWords = align(headInDWords)
|
headInDWords = align(headInDWords)
|
||||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||||
n := u.Sub[0].Uint32Count()
|
n := u.Sub[0].Uint32Count()
|
||||||
switch u.Sub[0].Main {
|
switch u.Sub[0].Main {
|
||||||
case shaderir.Mat2:
|
case Mat2:
|
||||||
n = 6
|
n = 6
|
||||||
case shaderir.Mat3:
|
case Mat3:
|
||||||
n = 11
|
n = 11
|
||||||
case shaderir.Mat4:
|
case Mat4:
|
||||||
n = 16
|
n = 16
|
||||||
}
|
}
|
||||||
headInDWords += (u.Length - 1) * align(n)
|
headInDWords += (u.Length - 1) * align(n)
|
||||||
// The last element is not with a padding.
|
// The last element is not with a padding.
|
||||||
headInDWords += n
|
headInDWords += n
|
||||||
case shaderir.Struct:
|
case Struct:
|
||||||
// TODO: Implement this
|
// TODO: Implement this
|
||||||
panic("hlsl: offset for a struct is not implemented yet")
|
panic("hlsl: offset for a struct is not implemented yet")
|
||||||
default:
|
default:
|
||||||
@ -102,5 +105,6 @@ func CalcUniformMemoryOffsetsInDWords(program *shaderir.Program) []int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return offsetsInDWords
|
p.offsetsInDWords = offsetsInDWords
|
||||||
|
return p.offsetsInDWords
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user