131 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package pass
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"github.com/vkngwrapper/core/v2/core1_0"
 | 
						|
	"github.com/vkngwrapper/extensions/v2/khr_swapchain"
 | 
						|
	"log"
 | 
						|
	"zworld/engine/object"
 | 
						|
	"zworld/engine/renderapi"
 | 
						|
	"zworld/engine/renderapi/command"
 | 
						|
	"zworld/engine/renderapi/descriptor"
 | 
						|
	"zworld/engine/renderapi/framebuffer"
 | 
						|
	"zworld/engine/renderapi/material"
 | 
						|
	"zworld/engine/renderapi/renderpass"
 | 
						|
	"zworld/engine/renderapi/renderpass/attachment"
 | 
						|
	"zworld/engine/renderapi/shader"
 | 
						|
	"zworld/engine/renderapi/texture"
 | 
						|
	"zworld/engine/renderapi/vertex"
 | 
						|
	"zworld/engine/renderapi/vulkan"
 | 
						|
)
 | 
						|
 | 
						|
type OutputPass struct {
 | 
						|
	app      vulkan.App
 | 
						|
	material *material.Material[*OutputDescriptors]
 | 
						|
	source   vulkan.Target
 | 
						|
 | 
						|
	quad  vertex.Mesh
 | 
						|
	desc  []*material.Instance[*OutputDescriptors]
 | 
						|
	tex   []texture.T
 | 
						|
	fbufs framebuffer.Array
 | 
						|
	pass  renderpass.T
 | 
						|
}
 | 
						|
 | 
						|
var _ Pass = &OutputPass{}
 | 
						|
 | 
						|
type OutputDescriptors struct {
 | 
						|
	descriptor.Set
 | 
						|
	Output *descriptor.Sampler
 | 
						|
}
 | 
						|
 | 
						|
func NewOutputPass(app vulkan.App, target vulkan.Target, source vulkan.Target) *OutputPass {
 | 
						|
	log.Println("create output pass")
 | 
						|
	p := &OutputPass{
 | 
						|
		app:    app,
 | 
						|
		source: source,
 | 
						|
	}
 | 
						|
 | 
						|
	p.quad = vertex.ScreenQuad("output-pass-quad")
 | 
						|
 | 
						|
	p.pass = renderpass.New(app.Device(), renderpass.Args{
 | 
						|
		Name: "Output",
 | 
						|
		ColorAttachments: []attachment.Color{
 | 
						|
			{
 | 
						|
				Name:        OutputAttachment,
 | 
						|
				Image:       attachment.FromImageArray(target.Surfaces()),
 | 
						|
				LoadOp:      core1_0.AttachmentLoadOpClear, // clearing avoids displaying garbage on the very first frame
 | 
						|
				FinalLayout: khr_swapchain.ImageLayoutPresentSrc,
 | 
						|
			},
 | 
						|
		},
 | 
						|
		Subpasses: []renderpass.Subpass{
 | 
						|
			{
 | 
						|
				Name:             MainSubpass,
 | 
						|
				ColorAttachments: []attachment.Name{OutputAttachment},
 | 
						|
			},
 | 
						|
		},
 | 
						|
	})
 | 
						|
 | 
						|
	p.material = material.New(
 | 
						|
		app.Device(),
 | 
						|
		material.Args{
 | 
						|
			Shader:     app.Shaders().Fetch(shader.NewRef("output")),
 | 
						|
			Pass:       p.pass,
 | 
						|
			Pointers:   vertex.ParsePointers(vertex.T{}),
 | 
						|
			DepthTest:  false,
 | 
						|
			DepthWrite: false,
 | 
						|
		},
 | 
						|
		&OutputDescriptors{
 | 
						|
			Output: &descriptor.Sampler{
 | 
						|
				Stages: core1_0.StageFragment,
 | 
						|
			},
 | 
						|
		})
 | 
						|
 | 
						|
	frames := target.Frames()
 | 
						|
	var err error
 | 
						|
	p.fbufs, err = framebuffer.NewArray(frames, app.Device(), "output", target.Width(), target.Height(), p.pass)
 | 
						|
	if err != nil {
 | 
						|
		panic(err)
 | 
						|
	}
 | 
						|
 | 
						|
	p.desc = p.material.InstantiateMany(app.Pool(), frames)
 | 
						|
	p.tex = make([]texture.T, frames)
 | 
						|
	for i := range p.tex {
 | 
						|
		key := fmt.Sprintf("gbuffer-output-%d", i)
 | 
						|
		p.tex[i], err = texture.FromImage(app.Device(), key, p.source.Surfaces()[i], texture.Args{
 | 
						|
			Filter: texture.FilterNearest,
 | 
						|
			Wrap:   texture.WrapClamp,
 | 
						|
		})
 | 
						|
		if err != nil {
 | 
						|
			// todo: clean up
 | 
						|
			panic(err)
 | 
						|
		}
 | 
						|
		p.desc[i].Descriptors().Output.Set(p.tex[i])
 | 
						|
	}
 | 
						|
 | 
						|
	return p
 | 
						|
}
 | 
						|
 | 
						|
func (p *OutputPass) Record(cmds command.Recorder, args renderapi.Args, scene object.Component) {
 | 
						|
	quad := p.app.Meshes().Fetch(p.quad)
 | 
						|
 | 
						|
	cmds.Record(func(cmd command.Buffer) {
 | 
						|
		cmd.CmdBeginRenderPass(p.pass, p.fbufs[args.Frame])
 | 
						|
		p.desc[args.Frame].Bind(cmd)
 | 
						|
		quad.Draw(cmd, 0)
 | 
						|
		cmd.CmdEndRenderPass()
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func (p *OutputPass) Name() string {
 | 
						|
	return "Output"
 | 
						|
}
 | 
						|
 | 
						|
func (p *OutputPass) Destroy() {
 | 
						|
	for _, tex := range p.tex {
 | 
						|
		tex.Destroy()
 | 
						|
	}
 | 
						|
	p.fbufs.Destroy()
 | 
						|
	p.pass.Destroy()
 | 
						|
	p.material.Destroy()
 | 
						|
}
 |