mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
Compare commits
3 Commits
ee8b289106
...
7d3007a43e
Author | SHA1 | Date | |
---|---|---|---|
|
7d3007a43e | ||
|
103b3fe11e | ||
|
beac278c59 |
@ -29,13 +29,20 @@ const (
|
||||
|
||||
ProjectionMatrixUniformVariableIndex = 6
|
||||
|
||||
PreservedUniformUint32Count = 2 + // the destination texture size
|
||||
PreservedUniformDwordCount = 2 + // the destination texture size
|
||||
2*ShaderSrcImageCount + // the source texture sizes array
|
||||
2 + // the destination image region origin
|
||||
2 + // the destination image region size
|
||||
2*ShaderSrcImageCount + // the source image region origins array
|
||||
2*ShaderSrcImageCount + // the source image region sizes array
|
||||
16 // the projection matrix
|
||||
|
||||
ProjectionMatrixUniformDwordIndex = 2 +
|
||||
2*ShaderSrcImageCount +
|
||||
2 +
|
||||
2 +
|
||||
2*ShaderSrcImageCount +
|
||||
2*ShaderSrcImageCount
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
func BenchmarkPrependPreservedUniforms(b *testing.B) {
|
||||
var uniforms [graphics.PreservedUniformUint32Count]uint32
|
||||
var uniforms [graphics.PreservedUniformDwordCount]uint32
|
||||
dst := graphicscommand.NewImage(16, 16, false, "")
|
||||
src := graphicscommand.NewImage(16, 16, false, "")
|
||||
dr := image.Rect(0, 0, 16, 16)
|
||||
|
@ -347,15 +347,15 @@ func imageRectangleToRectangleF32(r image.Rectangle) rectangleF32 {
|
||||
|
||||
func (q *commandQueue) prependPreservedUniforms(uniforms []uint32, shader *Shader, dst *Image, srcs [graphics.ShaderSrcImageCount]*Image, dstRegion image.Rectangle, srcRegions [graphics.ShaderSrcImageCount]image.Rectangle) []uint32 {
|
||||
origUniforms := uniforms
|
||||
uniforms = q.uint32sBuffer.alloc(len(origUniforms) + graphics.PreservedUniformUint32Count)
|
||||
copy(uniforms[graphics.PreservedUniformUint32Count:], origUniforms)
|
||||
uniforms = q.uint32sBuffer.alloc(len(origUniforms) + graphics.PreservedUniformDwordCount)
|
||||
copy(uniforms[graphics.PreservedUniformDwordCount:], origUniforms)
|
||||
return prependPreservedUniforms(uniforms, shader, dst, srcs, dstRegion, srcRegions)
|
||||
}
|
||||
|
||||
func prependPreservedUniforms(uniforms []uint32, shader *Shader, dst *Image, srcs [graphics.ShaderSrcImageCount]*Image, dstRegion image.Rectangle, srcRegions [graphics.ShaderSrcImageCount]image.Rectangle) []uint32 {
|
||||
// Set the destination texture size.
|
||||
// Hard-code indices for BCE optimization.
|
||||
_ = uniforms[graphics.PreservedUniformUint32Count-1]
|
||||
_ = uniforms[graphics.PreservedUniformDwordCount-1]
|
||||
|
||||
dw, dh := dst.InternalSize()
|
||||
uniforms[0] = math.Float32bits(float32(dw))
|
||||
@ -468,8 +468,8 @@ func prependPreservedUniforms(uniforms []uint32, shader *Shader, dst *Image, src
|
||||
return uniforms
|
||||
}
|
||||
|
||||
// Confirm the concrete value of graphics.PreservedUniformUint32Count.
|
||||
var _ [0]struct{} = [graphics.PreservedUniformUint32Count - 46]struct{}{}
|
||||
// Confirm the concrete value of graphics.PreservedUniformDwordCount.
|
||||
var _ [0]struct{} = [graphics.PreservedUniformDwordCount - 46]struct{}{}
|
||||
|
||||
type commandQueuePool struct {
|
||||
cache []*commandQueue
|
||||
|
@ -513,7 +513,7 @@ func (g *graphics11) NewShader(program *shaderir.Program) (graphicsdriver.Shader
|
||||
graphics: g,
|
||||
id: g.genNextShaderID(),
|
||||
uniformTypes: program.Uniforms,
|
||||
uniformOffsets: hlsl.UniformVariableOffsetsInDWords(program),
|
||||
uniformOffsets: hlsl.UniformVariableOffsetsInDwords(program),
|
||||
vertexShaderBlob: vsh,
|
||||
pixelShaderBlob: psh,
|
||||
}
|
||||
|
@ -1073,7 +1073,7 @@ func (g *graphics12) NewShader(program *shaderir.Program) (graphicsdriver.Shader
|
||||
graphics: g,
|
||||
id: g.genNextShaderID(),
|
||||
uniformTypes: program.Uniforms,
|
||||
uniformOffsets: hlsl.UniformVariableOffsetsInDWords(program),
|
||||
uniformOffsets: hlsl.UniformVariableOffsetsInDwords(program),
|
||||
vertexShader: vsh,
|
||||
pixelShader: psh,
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ func adjustUniforms(uniformTypes []shaderir.Type, uniformOffsets []int, uniforms
|
||||
fs = append(fs, make([]uint32, uniformOffsets[i]-len(fs))...)
|
||||
}
|
||||
|
||||
n := typ.Uint32Count()
|
||||
n := typ.DwordCount()
|
||||
switch typ.Main {
|
||||
case shaderir.Float:
|
||||
fs = append(fs, uniforms[idx:idx+1]...)
|
||||
|
@ -882,7 +882,7 @@ func adjustUniformVariablesLayout(uniformTypes []shaderir.Type, uniforms []uint3
|
||||
|
||||
var idx int
|
||||
for i, typ := range uniformTypes {
|
||||
n := typ.Uint32Count()
|
||||
n := typ.DwordCount()
|
||||
switch typ.Main {
|
||||
case shaderir.Float, shaderir.Int:
|
||||
values = append(values, uniforms[idx:idx+n]...)
|
||||
|
@ -224,7 +224,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
|
||||
|
||||
var idx int
|
||||
for i, typ := range shader.ir.Uniforms {
|
||||
n := typ.Uint32Count()
|
||||
n := typ.DwordCount()
|
||||
g.uniformVars[i].name = g.uniformVariableName(i)
|
||||
g.uniformVars[i].value = uniforms[idx : idx+n]
|
||||
g.uniformVars[i].typ = typ
|
||||
|
@ -292,7 +292,7 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
|
||||
if u.value == nil {
|
||||
continue
|
||||
}
|
||||
if got, expected := len(u.value), u.typ.Uint32Count(); got != expected {
|
||||
if got, expected := len(u.value), u.typ.DwordCount(); got != expected {
|
||||
// Copy a shaderir.Type value once. Do not pass u.typ directly to fmt.Errorf arguments, or
|
||||
// the value u would be allocated on heap.
|
||||
typ := u.typ
|
||||
|
@ -30,6 +30,11 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||
)
|
||||
|
||||
//export ebitengine_ProjectionMatrixUniformDwordIndex
|
||||
func ebitengine_ProjectionMatrixUniformDwordIndex() C.int {
|
||||
return C.int(graphics.ProjectionMatrixUniformDwordIndex)
|
||||
}
|
||||
|
||||
type playstation5Error struct {
|
||||
name string
|
||||
code int
|
||||
|
@ -25,6 +25,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int ebitengine_ProjectionMatrixUniformDwordIndex();
|
||||
|
||||
typedef struct ebitengine_Error {
|
||||
const char *message;
|
||||
int code;
|
||||
@ -52,23 +54,27 @@ typedef struct ebitengine_DstRegion {
|
||||
// kBlendFactor* and kBlendOperation* must be synced with
|
||||
// internal/graphicsdriver/blend.go.
|
||||
|
||||
const uint8_t kBlendFactorZero = 0;
|
||||
const uint8_t kBlendFactorOne = 1;
|
||||
const uint8_t kBlendFactorSourceColor = 2;
|
||||
const uint8_t kBlendFactorOneMinusSourceColor = 3;
|
||||
const uint8_t kBlendFactorSourceAlpha = 4;
|
||||
const uint8_t kBlendFactorOneMinusSourceAlpha = 5;
|
||||
const uint8_t kBlendFactorDestinationColor = 6;
|
||||
const uint8_t kBlendFactorOneMinusDestinationColor = 7;
|
||||
const uint8_t kBlendFactorDestinationAlpha = 8;
|
||||
const uint8_t kBlendFactorOneMinusDestinationAlpha = 9;
|
||||
const uint8_t kBlendFactorSourceAlphaSaturated = 10;
|
||||
enum {
|
||||
kBlendFactorZero = 0,
|
||||
kBlendFactorOne = 1,
|
||||
kBlendFactorSourceColor = 2,
|
||||
kBlendFactorOneMinusSourceColor = 3,
|
||||
kBlendFactorSourceAlpha = 4,
|
||||
kBlendFactorOneMinusSourceAlpha = 5,
|
||||
kBlendFactorDestinationColor = 6,
|
||||
kBlendFactorOneMinusDestinationColor = 7,
|
||||
kBlendFactorDestinationAlpha = 8,
|
||||
kBlendFactorOneMinusDestinationAlpha = 9,
|
||||
kBlendFactorSourceAlphaSaturated = 10,
|
||||
};
|
||||
|
||||
const uint8_t kBlendOperationAdd = 0;
|
||||
const uint8_t kBlendOperationSubtract = 1;
|
||||
const uint8_t kBlendOperationReverseSubtract = 2;
|
||||
const uint8_t kBlendOperationMin = 3;
|
||||
const uint8_t kBlendOperationMax = 4;
|
||||
enum {
|
||||
kBlendOperationAdd = 0,
|
||||
kBlendOperationSubtract = 1,
|
||||
kBlendOperationReverseSubtract = 2,
|
||||
kBlendOperationMin = 3,
|
||||
kBlendOperationMax = 4,
|
||||
};
|
||||
|
||||
typedef struct ebitengine_Blend {
|
||||
uint8_t factor_src_rgb;
|
||||
|
@ -27,7 +27,7 @@ func BenchmarkFilter(b *testing.B) {
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
uniforms := make([]uint32, graphics.PreservedUniformUint32Count)
|
||||
uniforms := make([]uint32, graphics.PreservedUniformDwordCount)
|
||||
for i := 0; i < b.N; i++ {
|
||||
s.FilterUniformVariables(uniforms)
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ float4x4 float4x4FromScalar(float x) {
|
||||
}`
|
||||
|
||||
func Compile(p *shaderir.Program) (vertexShader, pixelShader, prelude string) {
|
||||
offsets := UniformVariableOffsetsInDWords(p)
|
||||
offsets := UniformVariableOffsetsInDwords(p)
|
||||
|
||||
c := &compileContext{
|
||||
unit: p.Unit,
|
||||
@ -119,8 +119,8 @@ func Compile(p *shaderir.Program) (vertexShader, pixelShader, prelude string) {
|
||||
lines = append(lines, "cbuffer Uniforms : register(b0) {")
|
||||
for i, t := range p.Uniforms {
|
||||
// packingoffset is not mandatory, but this is useful to ensure the correct offset is used.
|
||||
offset := fmt.Sprintf("c%d", offsets[i]/UniformVariableBoundaryInDWords)
|
||||
switch offsets[i] % UniformVariableBoundaryInDWords {
|
||||
offset := fmt.Sprintf("c%d", offsets[i]/UniformVariableBoundaryInDwords)
|
||||
switch offsets[i] % UniformVariableBoundaryInDwords {
|
||||
case 1:
|
||||
offset += ".y"
|
||||
case 2:
|
||||
|
@ -20,10 +20,10 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||
)
|
||||
|
||||
const UniformVariableBoundaryInDWords = 4
|
||||
const UniformVariableBoundaryInDwords = 4
|
||||
|
||||
// UniformVariableOffsetsInDWords returns the offsets of the uniform variables in DWROD units in the HLSL layout.
|
||||
func UniformVariableOffsetsInDWords(program *shaderir.Program) []int {
|
||||
// UniformVariableOffsetsInDwords returns the offsets of the uniform variables in DWROD units in the HLSL layout.
|
||||
func UniformVariableOffsetsInDwords(program *shaderir.Program) []int {
|
||||
// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules
|
||||
// https://github.com/microsoft/DirectXShaderCompiler/wiki/Buffer-Packing
|
||||
|
||||
@ -31,59 +31,59 @@ func UniformVariableOffsetsInDWords(program *shaderir.Program) []int {
|
||||
if x == 0 {
|
||||
return 0
|
||||
}
|
||||
return ((x-1)/UniformVariableBoundaryInDWords + 1) * UniformVariableBoundaryInDWords
|
||||
return ((x-1)/UniformVariableBoundaryInDwords + 1) * UniformVariableBoundaryInDwords
|
||||
}
|
||||
|
||||
var offsetsInDWords []int
|
||||
var headInDWords int
|
||||
var offsetsInDwords []int
|
||||
var headInDwords int
|
||||
|
||||
// TODO: Reorder the variables with packoffset.
|
||||
// See https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-variable-packoffset
|
||||
for _, u := range program.Uniforms {
|
||||
switch u.Main {
|
||||
case shaderir.Float:
|
||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||
headInDWords += 1
|
||||
offsetsInDwords = append(offsetsInDwords, headInDwords)
|
||||
headInDwords += 1
|
||||
case shaderir.Int:
|
||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||
headInDWords += 1
|
||||
offsetsInDwords = append(offsetsInDwords, headInDwords)
|
||||
headInDwords += 1
|
||||
case shaderir.Vec2, shaderir.IVec2:
|
||||
if headInDWords%UniformVariableBoundaryInDWords >= 3 {
|
||||
headInDWords = align(headInDWords)
|
||||
if headInDwords%UniformVariableBoundaryInDwords >= 3 {
|
||||
headInDwords = align(headInDwords)
|
||||
}
|
||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||
headInDWords += 2
|
||||
offsetsInDwords = append(offsetsInDwords, headInDwords)
|
||||
headInDwords += 2
|
||||
case shaderir.Vec3, shaderir.IVec3:
|
||||
if headInDWords%UniformVariableBoundaryInDWords >= 2 {
|
||||
headInDWords = align(headInDWords)
|
||||
if headInDwords%UniformVariableBoundaryInDwords >= 2 {
|
||||
headInDwords = align(headInDwords)
|
||||
}
|
||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||
headInDWords += 3
|
||||
offsetsInDwords = append(offsetsInDwords, headInDwords)
|
||||
headInDwords += 3
|
||||
case shaderir.Vec4, shaderir.IVec4:
|
||||
if headInDWords%UniformVariableBoundaryInDWords >= 1 {
|
||||
headInDWords = align(headInDWords)
|
||||
if headInDwords%UniformVariableBoundaryInDwords >= 1 {
|
||||
headInDwords = align(headInDwords)
|
||||
}
|
||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||
headInDWords += 4
|
||||
offsetsInDwords = append(offsetsInDwords, headInDwords)
|
||||
headInDwords += 4
|
||||
case shaderir.Mat2:
|
||||
// For matrices, each column is aligned to the boundary.
|
||||
headInDWords = align(headInDWords)
|
||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||
headInDWords += 6
|
||||
headInDwords = align(headInDwords)
|
||||
offsetsInDwords = append(offsetsInDwords, headInDwords)
|
||||
headInDwords += 6
|
||||
case shaderir.Mat3:
|
||||
headInDWords = align(headInDWords)
|
||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||
headInDWords += 11
|
||||
headInDwords = align(headInDwords)
|
||||
offsetsInDwords = append(offsetsInDwords, headInDwords)
|
||||
headInDwords += 11
|
||||
case shaderir.Mat4:
|
||||
headInDWords = align(headInDWords)
|
||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||
headInDWords += 16
|
||||
headInDwords = align(headInDwords)
|
||||
offsetsInDwords = append(offsetsInDwords, headInDwords)
|
||||
headInDwords += 16
|
||||
case shaderir.Array:
|
||||
// Each array is 16-byte aligned.
|
||||
// TODO: What if the array has 2 or more dimensions?
|
||||
headInDWords = align(headInDWords)
|
||||
offsetsInDWords = append(offsetsInDWords, headInDWords)
|
||||
n := u.Sub[0].Uint32Count()
|
||||
headInDwords = align(headInDwords)
|
||||
offsetsInDwords = append(offsetsInDwords, headInDwords)
|
||||
n := u.Sub[0].DwordCount()
|
||||
switch u.Sub[0].Main {
|
||||
case shaderir.Mat2:
|
||||
n = 6
|
||||
@ -92,9 +92,9 @@ func UniformVariableOffsetsInDWords(program *shaderir.Program) []int {
|
||||
case shaderir.Mat4:
|
||||
n = 16
|
||||
}
|
||||
headInDWords += (u.Length - 1) * align(n)
|
||||
headInDwords += (u.Length - 1) * align(n)
|
||||
// The last element is not with a padding.
|
||||
headInDWords += n
|
||||
headInDwords += n
|
||||
case shaderir.Struct:
|
||||
// TODO: Implement this
|
||||
panic("hlsl: offset for a struct is not implemented yet")
|
||||
@ -103,5 +103,5 @@ func UniformVariableOffsetsInDWords(program *shaderir.Program) []int {
|
||||
}
|
||||
}
|
||||
|
||||
return offsetsInDWords
|
||||
return offsetsInDwords
|
||||
}
|
||||
|
@ -493,7 +493,7 @@ func (p *Program) FilterUniformVariables(uniforms []uint32) {
|
||||
p.uniformFactors = make([]uint32, len(uniforms))
|
||||
var idx int
|
||||
for i, typ := range p.Uniforms {
|
||||
c := typ.Uint32Count()
|
||||
c := typ.DwordCount()
|
||||
if reachableUniforms[i] {
|
||||
for i := idx; i < idx+c; i++ {
|
||||
p.uniformFactors[i] = 1
|
||||
|
@ -87,7 +87,7 @@ func (t Type) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (t Type) Uint32Count() int {
|
||||
func (t Type) DwordCount() int {
|
||||
switch t.Main {
|
||||
case Int:
|
||||
return 1
|
||||
@ -112,7 +112,7 @@ func (t Type) Uint32Count() int {
|
||||
case Mat4:
|
||||
return 16
|
||||
case Array:
|
||||
return t.Length * t.Sub[0].Uint32Count()
|
||||
return t.Length * t.Sub[0].DwordCount()
|
||||
default: // TODO: Parse a struct correctly
|
||||
return -1
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ import (
|
||||
type Shader struct {
|
||||
shader *atlas.Shader
|
||||
|
||||
uniformNames []string
|
||||
uniformTypes []shaderir.Type
|
||||
uniformUint32Count int
|
||||
uniformNames []string
|
||||
uniformTypes []shaderir.Type
|
||||
uniformDwordCount int
|
||||
}
|
||||
|
||||
func NewShader(ir *shaderir.Program, name string) *Shader {
|
||||
@ -45,20 +45,20 @@ func (s *Shader) Deallocate() {
|
||||
}
|
||||
|
||||
func (s *Shader) AppendUniforms(dst []uint32, uniforms map[string]any) []uint32 {
|
||||
if s.uniformUint32Count == 0 {
|
||||
if s.uniformDwordCount == 0 {
|
||||
for _, typ := range s.uniformTypes {
|
||||
s.uniformUint32Count += typ.Uint32Count()
|
||||
s.uniformDwordCount += typ.DwordCount()
|
||||
}
|
||||
}
|
||||
|
||||
origLen := len(dst)
|
||||
if cap(dst)-len(dst) >= s.uniformUint32Count {
|
||||
dst = dst[:len(dst)+s.uniformUint32Count]
|
||||
if cap(dst)-len(dst) >= s.uniformDwordCount {
|
||||
dst = dst[:len(dst)+s.uniformDwordCount]
|
||||
for i := origLen; i < len(dst); i++ {
|
||||
dst[i] = 0
|
||||
}
|
||||
} else {
|
||||
dst = append(dst, make([]uint32, s.uniformUint32Count)...)
|
||||
dst = append(dst, make([]uint32, s.uniformDwordCount)...)
|
||||
}
|
||||
|
||||
idx := origLen
|
||||
@ -71,23 +71,23 @@ func (s *Shader) AppendUniforms(dst []uint32, uniforms map[string]any) []uint32
|
||||
t := v.Type()
|
||||
switch t.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if typ.Uint32Count() != 1 {
|
||||
if typ.DwordCount() != 1 {
|
||||
panic(fmt.Sprintf("ui: unexpected uniform value for %s (%s)", name, typ.String()))
|
||||
}
|
||||
dst[idx] = uint32(v.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
if typ.Uint32Count() != 1 {
|
||||
if typ.DwordCount() != 1 {
|
||||
panic(fmt.Sprintf("ui: unexpected uniform value for %s (%s)", name, typ.String()))
|
||||
}
|
||||
dst[idx] = uint32(v.Uint())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
if typ.Uint32Count() != 1 {
|
||||
if typ.DwordCount() != 1 {
|
||||
panic(fmt.Sprintf("ui: unexpected uniform value for %s (%s)", name, typ.String()))
|
||||
}
|
||||
dst[idx] = math.Float32bits(float32(v.Float()))
|
||||
case reflect.Slice, reflect.Array:
|
||||
l := v.Len()
|
||||
if typ.Uint32Count() != l {
|
||||
if typ.DwordCount() != l {
|
||||
panic(fmt.Sprintf("ui: unexpected uniform value for %s (%s)", name, typ.String()))
|
||||
}
|
||||
switch t.Elem().Kind() {
|
||||
@ -111,7 +111,7 @@ func (s *Shader) AppendUniforms(dst []uint32, uniforms map[string]any) []uint32
|
||||
}
|
||||
}
|
||||
|
||||
idx += typ.Uint32Count()
|
||||
idx += typ.DwordCount()
|
||||
}
|
||||
|
||||
return dst
|
||||
|
Loading…
Reference in New Issue
Block a user