2 คะแนน โดย GN⁺ 2024-09-03 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • paraLLEl-GS จำลอง GS (Graphics Synthesizer) ของ PS2 ด้วย Vulkan compute เพื่อจัดการข้อจำกัดด้านความถูกต้องและการอัปสเกลที่ GSdx ซึ่งเป็นมาตรฐานโดยพฤตินัยมาเกือบ 20 ปีทิ้งไว้
  • GS ทำงานบน VRAM 4MiB และ fill rate สูง แต่ด้วยคุณสมบัติของ pixel pipeline เช่น destination alpha test, conditional blending และค่า alpha/color ที่เกิน 1.0 จึงทำให้ยากที่จะทำให้ตรงด้วย graphics API ทั่วไป
  • การใช้งานติดตาม VRAM เป็นหน่วย page และ block ขนาด 256 ไบต์ และผสาน CLUT snapshot, texture unswizzle และการจัดชุด render pass เพื่อจัดการ framebuffer/texture feedback
  • มีการเปรียบเทียบปัญหาด้านการอัปสเกล, UI, high-precision blending และ texture feedback ในกรณีอย่าง Tales of the Abyss, Final Fantasy X, MGS2, Valkyrie Profile 2 และ Shadow of the Colossus รวมถึงฉาก 8x/16x SSAA
  • ปัจจุบันการตรวจสอบอาศัยการเล่นซ้ำ GS dump เป็นหลัก แม้จะมี patch แบบแฮ็กสำหรับ PCSX2 และการทดสอบเรียลไทม์ด้วย mkfifo แต่หากต้องการให้ถึงมือผู้ใช้จริง ยังจำเป็นต้องผสานเข้ากับ emulator

เป้าหมายและจุดเริ่มต้นของ paraLLEl-GS

  • paraLLEl-GS เป็นโปรเจกต์จำลอง GS (Graphics Synthesizer) ของ PlayStation 2 ด้วย Vulkan compute
  • งานปี 2020 ของผู้เขียนคนเดียวกันอย่าง paraLLEl-RDP ได้นำ N64 RDP มาใช้งานด้วย Vulkan compute โดยตั้งเป้าให้ได้ผลลัพธ์ใกล้เคียง bit-exact เมื่อเทียบกับ Angrylion และรองรับการอัปสเกล
  • สำหรับ PS2 นั้น GSdx ยังคงเป็น implementation ระดับแนวหน้าตามพฤตินัยมาเกือบ 20 ปี
  • ราวปี 2014 เคยมีความพยายามทำ PS2 GS compute implementation บน OpenCL แต่ไม่เสร็จสมบูรณ์ และปัจจุบันก็หาได้ยากใน upstream repository
  • เหตุผลที่ต้องใช้ compute shader raster บน PS2 นั้นอ่อนกว่า N64
    • PCSX2 มี software renderer ที่ปรับแต่งมาดี และ renderer แบบใช้กราฟิกที่ค่อนข้างแข็งแรง
    • software renderer ไม่รองรับการอัปสเกล
    • renderer แบบใช้กราฟิกมีบั๊กและ glitch หลายอย่าง โดยเฉพาะเมื่ออัปสเกล
  • paraLLEl-GS เน้นหลีกเลี่ยงปัญหาความถูกต้องที่เห็นได้ชัด มากกว่าการทำให้ bit-exact กับฮาร์ดแวร์
    • software renderer ของ GSdx เองก็ดูไม่ใช่ implementation ที่ bit-exact กับฮาร์ดแวร์ ทำให้การทดสอบแบบเทียบกันโดยตรงชนขีดจำกัดอย่างรวดเร็ว

ทำไม PS2 GS จึงรับมือยาก

  • ในปี 2000 GS เป็นอุปกรณ์ที่ตามทฤษฎีมี fill rate และ bandwidth ที่ประมวลผลได้มากกว่า 1 พันล้านพิกเซลต่อวินาที
  • VRAM มีขนาดเล็กเพียง 4MiB แต่ถูกออกแบบให้สตรีมข้อมูลอย่างต่อเนื่องผ่าน DMA engine หลายตัว
  • pixel pipeline เองมีบางด้านที่เรียบง่ายกว่า N64 RDP
    • texture เดียว
    • single-cycle combiner
    • anti-aliasing แบบพื้นฐานมาก
  • มีฟีเจอร์จำนวนมากที่ทำได้ยากด้วย graphics API ทั่วไป
    • blending ที่เกิน 1.0: เป็นพฤติกรรมที่สืบต่อมาจาก PS1 โดย 0x80 ถูกปฏิบัติเสมือน 1.0 และสามารถแสดงค่าได้ถึง 0xff
    • destination alpha test: สามารถใช้ destination alpha คล้าย stencil ได้
    • conditional blending: สามารถปิด blending แบบมีเงื่อนไขตาม alpha ได้
    • alpha correction: ก่อนบันทึก alpha สามารถ OR ค่า MSB เพื่อบังคับให้เข้าใกล้ 1 ได้
    • การ discard บางส่วนของ alpha test: ทำพฤติกรรมแบบทิ้งเฉพาะสี แต่ยังคงบันทึก depth ได้
    • AA1: เป็นแบบ coverage-to-alpha และเกี่ยวพันกับการควบคุมการบันทึก depth รายพิกเซล
    • Z แบบ fixed-point 32 บิต: แม้ D32_UINT จะรองรับในทางเทคนิค แต่ยังไม่พบกรณีใช้งานจริง
  • หากไม่มี programmable blending บน immediate-mode desktop GPU จะต้องใช้ ROV หรือ barrier รายพิกเซล ทำให้ประสิทธิภาพแย่ลงมาก
  • implementation แบบ compute สร้าง tile-based deferred renderer (TBDR) ของตัวเองเพื่อเลี่ยงข้อจำกัดเหล่านี้

กฎ raster, vertex queue และการจัดวางหน่วยความจำ

  • primitive ของ GS ถูกส่งมาใน clip space ค่อนข้างธรรมดา
    • VU1 ทำการ transform และ clipping แล้วส่งออก vertex attribute หลายอย่างไปยัง GS
  • พิกัดและ attribute มีรูปแบบเฉพาะของ GS
    • X/Y: unsigned fixed-point 12.4
    • Z: uint 24 บิตหรือ 32 บิต
    • FOG: uint 8 บิต
    • RGBA: ค่า 8 บิตสำหรับแสงต่อ vertex
    • STQ: พิกัด texture แบบ perspective-correct
    • UV: พิกัดที่ไม่ normalize แบบ fixed-point 12.4 โดยไม่มี perspective correction
  • กฎ raster ใกล้เคียงสไตล์ D3D9
    • triangle ใช้กฎ top-left raster เหมือน GPU สมัยใหม่
    • จุดกึ่งกลางพิกเซลอยู่ที่พิกัดจำนวนเต็มเหมือน D3D9
    • line ใช้อัลกอริทึม Bresenham จึงอัปสเกลได้ยาก และต้องประมาณด้วย rect หรือ parallelogram
    • point จะ snap ไปยังพิกเซลที่ใกล้ที่สุด
    • sprite เป็น quad แบบง่ายที่มีสองพิกัด
  • vertex queue ของ GS คล้าย immediate mode ของ OpenGL 1.0
    • ตั้งค่า RGBA, STQ และ register หลายตัว แล้วการเขียน XYZ register จะกลายเป็น vertex “kick”
    • รองรับ TRIANGLE_FAN ด้วย
  • พิกัดพิกเซลของ PS2 ถูกจัดวางเป็นหน่วย page
    • หนึ่ง page มีขนาด 8KiB
    • page ถูกแบ่งเป็น 32 block
    • สำหรับ RGBA 32 บิต หนึ่ง page คือ 64×32 พิกเซล และ block ขนาด 8×8 จำนวน 32 block จะถูก swizzle แบบ Z-order
  • เมื่อ render เป็นสี 24 บิตหรือ depth 24 บิต สามารถวาง texture ไว้ใน 8 บิตบนสุดที่เหลือได้
    • format 8H, 4HL, 4HH มีประโยชน์สำหรับ palette แบบ 8 บิตและ 4 บิต

Texture, CLUT และ TEXFLUSH

  • texture ของ GS ผสมทั้งส่วนที่คล้าย API สมัยใหม่และส่วนที่แปลกเฉพาะตัว
    • จุดกึ่งกลาง texel อยู่ที่ half-pixel เหมือน API สมัยใหม่
    • ความละเอียดระดับ sub-texel ดูเหมือนเป็น 4 บิต ไม่ใช่ 8 บิต
    • bilinear filter เป็น bilinear ทั่วไป ไม่ใช่โครงสร้างพิเศษอย่าง 3-point filter ของ N64
  • addressing mode พิเศษทำให้ความยากในการ implementation สูงขึ้น
    • REGION_CLAMP สามารถใช้ clamp กับพื้นที่任意ภายใน texture atlas ได้
    • REGION_REPEAT ทำ bit operation เช่น (u & MASK) | FIX กับแต่ละพิกัดได้ จึง implement ได้ยากกว่า
  • mipmapping คำนวณ LOD จาก log2 ของ Q factor ที่ interpolate แล้วและ scale coefficient แทนการใช้ derivative
    • ใน compute implementation การไม่พึ่ง derivative ถือเป็นข้อได้เปรียบใหญ่
    • วิธีนี้ไม่สามารถรองรับฟีเจอร์อย่าง anisotropic filtering ได้
  • CLUT คือ cache ขนาด 1KiB ที่เก็บ palette ปัจจุบัน
    • ต้อง copy จาก VRAM ไปยัง CLUT cache อย่างชัดเจนจึงจะใช้งานได้
    • สำหรับสี 32 บิต สามารถเก็บ palette 256 สีได้หนึ่งชุด
    • สำหรับ 16bpp สามารถเก็บ palette 16 สีได้ 32 ชุด
  • TEXFLUSH เป็นคำสั่ง explicit ที่ใกล้เคียงกับการซิงก์และ invalidate texture cache
    • ช่วงแรกของ implementation ตั้งใจจะใช้ TEXFLUSH เป็นเกณฑ์สำหรับ hazard tracking แต่สุดท้ายต้องเพิกเฉย
    • มีปัญหาที่เกมลืมเรียก TEXFLUSH หรือเรียกบ่อยเกินไป
  • implementation สุดท้ายเลือกแนวทาง minimal caching
    • ถือว่าไม่มี cache แล้วติดตาม hazard โดยตรง
    • พิจารณาการจัดการข้อยกเว้นแยกต่างหากสำหรับ feedback loop
    • GSdx ก็ดูเหมือนไปในทิศทางเดียวกัน

Rendering pipeline แบบ Vulkan compute

  • pipeline ของ implementation ถูกออกแบบโดยมีการซิงก์ระหว่างแต่ละขั้นเป็นพื้นฐาน
    • ซิงก์สำเนา VRAM ฝั่ง CPU กับ GPU
    • อัปโหลด VRAM หรือทำ local-to-local copy
    • อัปเดต CLUT cache จาก VRAM
    • unswizzle VRAM เป็น VkImage เพื่อให้ sample ได้โดยตรง
    • ทำการ rendering
    • ซิงก์สำเนา GPU VRAM กลับไปยัง CPU
  • พฤติกรรมทั่วไปของเกมเข้ากับ pipeline นี้ได้ดี
    • อัปโหลด texture ไปยัง VRAM
    • อัปโหลด palette ไปยัง VRAM
    • อัปเดต CLUT cache
    • draw ด้วย texture
    • หากจำเป็น ให้ unswizzle จาก VRAM เป็น VkImage
    • จัดชุด primitive เป็น render pass
  • หากไม่มี hazard ที่ย้อนกลับ สามารถหน่วงการจัด batch และการซิงก์ได้
    • สำหรับ renderer แนวนี้ การ รักษา batch ไว้เป็นสิ่งสำคัญต่อประสิทธิภาพ
  • กรณี hazard หลักถูกจัดการแยกต่างหาก
    • copy ซ้ำไปยัง VRAM ที่ถูกเขียนด้วย copy ไปแล้ว
    • copy ไปยัง VRAM ที่ถูกอ่านโดย texture หรือ CLUT ที่ถูก sample
    • sample พื้นที่ที่ render แล้วเป็น texture
    • copy ไปยัง VRAM ที่ render แล้ว

การติดตาม page และ texture cache

  • ส่วนที่ยากที่สุดของการจำลอง GS คือการจัดการ hazard แบบ read-after-write และ write-after-write ใน VRAM
  • VRAM 4MiB ถูกแบ่งเป็นหน่วย page ก่อน
    • page เป็นหน่วยของ framebuffer และ depth buffer จึงเป็นเกณฑ์ติดตามที่มีความหมายที่สุด
  • สถานะที่ติดตามในระดับ page มีดังนี้
    • pending frame buffer write
    • pending frame buffer read
  • texture และ VRAM copy มี alignment 256 ไบต์ จึงใช้ bitmask แบบ u32 สำหรับ block 32 ก้อน
    • VRAM copy write
    • VRAM copy read
    • pending read ไปยัง CLUT cache หรือ VkImage
    • block ที่ถูกเขียนทับด้วย write ใด ๆ
  • ในกรณีที่ render เป็นสี 24 บิตแล้ว sample 8 บิตบนสุดเป็น texture อาจไม่มี hazard
    • เพื่อสิ่งนี้ จึงติดตาม framebuffer write mask และ texture read mask แยกกัน
  • แต่ละ page มีรายการ VkImage ที่เชื่อมโยงอยู่
    • เมื่อ texture ของ page ถูก invalidate ภาพจะถูกทำลายและต้อง unswizzle ใหม่จาก VRAM
    • texture หนึ่งตัวอาจครอบคลุมหลาย page และหาก page ใด page หนึ่งถูกเขียนทับ texture ก็จะถูก invalidate
  • การติดตามแบบเรียบง่ายและ conservative อย่างเดียวไม่ทำงานกับเกม PS2
    • การติดตามระดับ block 256 ไบต์ และการพิจารณา write/read mask เป็นสิ่งสำคัญ
  • อาจเกิด false positive เนื่องจาก POT texture และการไม่ใช้ REGION_CLAMP
    • ตัวอย่างเช่น หากตั้ง render target 512×448 เป็น texture 512×512 พื้นที่ที่ไม่ได้ใช้อาจดูเหมือนเป็น hazard
    • implementation ใช้วิธี workaround ที่เพิกเฉยต่อ hazard ที่อาจเกิดขึ้นใน “red zone” นั้น

การจัด batch ของ CLUT และ texture unswizzle

  • หากต้องการ batch การอัปโหลด texture ก็ต้อง batch การอัปโหลด CLUT ไปพร้อมกันด้วย
  • implementation มีสำเนา CLUT 1024 ชุดเป็น snapshot ring buffer
    • workgroup หนึ่งวนอัปเดตและเขียนลง SSBO
    • คล้ายกับการอัปเดต TMEM ของ N64 RDP แต่การอัปเดต CLUT เรียบง่ายกว่ามาก
  • ใน Vulkan จะ allocate VkImage ใหม่ sub-allocate จาก VkDeviceMemory แล้วใช้ compute shader ทำ unswizzle
  • ใช้ Vulkan specialization constants เพื่อ specialize format ของ texture และ logic การ swizzle
  • พฤติกรรมพิเศษของ REGION_REPEAT ก็ถูกจัดการในขั้นตอน unswizzle ด้วย
    • หลังจากนั้น ubershader จึงลดความจำเป็นในการคำนึงถึงกรณีนี้เพื่อทำ manual bilinear filtering
  • render target ก็เดินทางไปกลับผ่าน VRAM SSBO เป็น texture
    • ความพยายามที่จะ forward render target เป็น texture โดยตรงถูกตัดสินว่ามีบั๊กและข้อยกเว้นมากเกินไป

Triangle setup, binning และ ubershader

  • paraLLEl-GS เป็น tile-based renderer เช่นเดียวกับ paraLLEl-RDP
  • ทำ triangle setup ก่อน binning โดย input แบ่งเป็นสาม array
    • ตำแหน่ง
    • attribute ต่อ vertex
    • attribute ต่อ primitive
  • rasterizer อิง barycentric และได้รับอิทธิพลอย่างมากจากวิธี parallel rasterization ที่อธิบายในบทความ graphics pipeline ของ Fabian Giesen และงานวิจัย Pineda 1988
  • PS2 GS จริงเป็น DDA หรือ scanline rasterizer แต่เนื่องจากไม่ทราบคำอธิบายแบบ bit-exact ของ GS DDA จึงใช้วิธี barycentric
  • รองรับ parallelogram ด้วยเพื่อทำ wide line และ sprite
  • inv_area คำนวณด้วย RCP แบบ fixed-point ที่กำหนดเอง
    • เลี่ยง RCP มาตรฐานของ GPU เพราะความสม่ำเสมอขึ้นกับ implementation และมีความแม่นยำประมาณ 22.5 บิต
    • RCP ที่กำหนดเองตั้งเป้าความแม่นยำประมาณ 24.0 บิต
  • binning ปกติใช้ block ขนาด 32×32 พิกเซล
    • จำนวน primitive สูงสุดต่อ render pass คือ 64k เนื่องจากดัชนี u16
    • render pass หลักที่พบโดยทั่วไปอยู่ในช่วง 10k~30k primitive
  • PS2 GS มี fill rate สูงและความซับซ้อนต่อพิกเซลต่ำ จึงสามารถใช้ ubershader ล้วน ได้
    • ต่างจาก N64 ตรงที่สามารถใช้ bindless ได้ ทำให้ความซับซ้อนของ texturing ลดลงด้วย
  • ubershader ใช้ early Z, deferred on-tile shading และ lazy pixel shading
    • จะทำ shading จริงเฉพาะเมื่อพิกเซลขึ้นกับผลลัพธ์ก่อนหน้าเท่านั้น
    • alpha test, color write mask, alpha blending เป็นต้น สร้าง dependency แบบนี้
    • สี framebuffer สุดท้ายและ depth ถูกบันทึกลง SSBO เพื่อลดการใช้ GPU bandwidth

Supersampling และการลด artifact จากการอัปสเกล

  • หาก render แบบ sample เดียวอย่างเดียว renderer นี้ยังมีประโยชน์ไม่เพียงพอ
  • ตัวอย่างเช่น ใน 8x SSAA จะเก็บ VRAM 10 เวอร์ชันไว้บน GPU
    • VRAM sample เดียว 1 ชุด
    • ค่า reference ของ VRAM sample เดียว 1 ชุด
    • supersample 8 ชุด
  • เมื่อ render หาก VRAM sample เดียวตรงกับ reference จะโหลดเวอร์ชัน supersample
    • สำคัญต่อ incremental rendering
  • เมื่อ tile เสร็จ จะทำ multisample resolve ด้วย clustered subgroup operation แล้วบันทึก supersample และสำเนา sample เดียว
  • supersampling มีรอยหยักน้อยกว่าการอัปสเกลแบบง่าย และทำให้ความรู้สึกด้านความละเอียดขององค์ประกอบ 3D กับ UI สอดคล้องกันมากขึ้น
  • sprite primitive ต้อง render แบบ single-rate เสมอ
    • ส่วนใหญ่เป็น UI หรือองค์ประกอบคล้ายกัน และหากอัปสเกล อาจ sample นอก rect ที่ตั้งใจไว้หรือเบลอเกินไปจาก bilinear filtering
  • UI จำนวนมากถูกวาดด้วย triangle ปกติ ดังนั้น primitive แบบ flat บางส่วนจึงลดการ interpolate attribute ลงสู่พิกัด single-pixel
    • แม้ใช้ perspective แต่หาก Q ของทุก vertex เท่ากันและ Z ก็เท่ากัน จะสันนิษฐานว่าเป็น flat UI primitive
    • อาจมี false positive ได้ แต่ในเกมที่ทดสอบ วิธีนี้ทำงานได้ดีพอ

ผลลัพธ์ตามเกมและกรณียาก

  • ใน Tales of the Abyss พบการจัดแนว bloom ของ Yulia ที่ไม่ตรงและลวดลายสี่เหลี่ยมในอัปสเกลของ PCSX2 Vulkan backend
    • ใน 8x SSAA ของ paraLLEl-GS ปัญหาทั่วไปของการอัปสเกลที่ไม่ดีไม่ค่อยปรากฏ
    • screenshot ดังกล่าวยังใช้ post-process upscale ของ FSR1 ด้วย
  • UI ของ Final Fantasy X แสดงปัญหาการอัปสเกลเมื่อเทียบ native resolution กับ 4x upscale
    • MSAA snap trick มีประสิทธิภาพในการหลีกเลี่ยง artifact
    • หลักสำคัญคืออย่าอัปสเกล UI เกิน nearest neighbor integer scale
  • MGS2 มีกรณีที่ต้องการ blending accuracy สูงใน PCSX2
    • PCSX2 ใส่ barrier ต่อ primitive ใน programmable blending path ทำให้ประสิทธิภาพตกลงมาก
    • paraLLEl-GS มีโครงสร้างที่ทำงานด้วย blend accuracy 100% เสมอ และมีการยกตัวอย่างฉาก 16x SSAA บน RX 7600 ที่ใช้ 25W และ GPU utilization 17%
  • Valkyrie Profile 2 มีกรณี sample alpha ของพิกเซลตัวเองเป็น palette index
    • paraLLEl-GS ตรวจจับสิ่งนี้ ทำให้ texture index เป็นค่าพิเศษ และอ้างอิง in-register framebuffer color
    • การปรับแต่งนี้ลด render pass barrier จากมากกว่า 500 เหลือ 18
  • เอฟเฟกต์ camo ใน intro ของ MGS2 sample framebuffer เป็น texture แต่ใช้พิกัดซ้อนทับที่การจัดแนวพิกเซลไม่ตรงกัน
    • PCSX2 ก็ดูเหมือนไม่เพิ่ม barrier ที่นี่ และ paraLLEl-GS ก็จัดการแบบเดียวกัน
  • Shadow of the Colossus ทำหน้าที่เป็น stress test ที่หนัก
    • ใน PCSX2 ที่ maximum blend accuracy แค่ 2x upscale ใน intro ก็ทำให้ GPU ลดลงเหลือ 24 FPS
    • paraLLEl-GS ยังมีประสิทธิภาพดีแม้ที่ 8x SSAA แต่ในฉากดังกล่าวภาระจะหนักขึ้น
    • กรณีนี้คอขวดอยู่ที่ geometry processing ของ CPU มากกว่า GPU

สถานะปัจจุบันและขั้นตอนถัดไป

  • วิธีทดสอบที่ใช้งานได้จริงในปัจจุบันคือการใช้ GS dump
  • มี hack-patch ที่ทำให้ PCSX2 dump raw GS trace ได้
  • สามารถทดสอบเรียลไทม์แบบหยาบ ๆ ผ่าน mkfifo ได้เช่นกัน
  • หากต้องการให้เป็นประโยชน์กับผู้ใช้ปลายทาง จำเป็นต้องมีการผสานเข้ากับ emulator ในรูปแบบใดรูปแบบหนึ่ง
  • เนื่องจากไลบรารีของ PS2 มีขนาดใหญ่มาก จึงมีความเป็นไปได้สูงว่ายังมีบั๊กจำนวนมากซ่อนอยู่
  • ด้วยลักษณะเป็น standalone library จึงยังมี use case ที่เป็นไปได้ในการใช้งานเหมือน rendering API แบบเก่า

1 ความคิดเห็น

 
GN⁺ 2024-09-03
ความคิดเห็นจาก Hacker News
  • รู้สึกว่าต้องหาอยู่นานว่าในบทความนี้ตัวย่อ GS ถูกขยายความไว้ตรงไหน เนื้อหาน่าสนใจ แต่ตรงนี้ทำให้รู้สึกตามไม่ค่อยทัน

    • ย่อมาจาก Graphics Synthesizer และเป็นชื่อที่ Sony ตั้งให้กับ “GPU” ของ PS2
  • ประโยค “จงภาวนาให้มี programmable blending” นี่ หลังจากได้เรียน pixel shader ครั้งแรกช่วงต้นยุค 2000 ก็เฝ้าหวัง programmable blending ผ่าน “blending shader” มาตลอด
    อีกอย่าง ยังอยากได้ programmable texture decoding ผ่าน “texture shader” ด้วย ซึ่งน่าจะมีประโยชน์กับรูปแบบ/การบีบอัด texture แบบกำหนดเอง การผสม texture ฯลฯ
    กลายเป็นว่า GPU ได้ ray tracing มาก่อน programmable blending เสียอีก ทั้งที่อย่างแรกเหมือนความฝันคืนฤดูร้อน ส่วนอย่างหลังรู้สึกเหมือนแค่เปลี่ยนบล็อกฟังก์ชันตายตัวอีกตัวให้เป็นบล็อกที่โปรแกรมได้เท่านั้น ส่วน texture shader ก็ยังคงรอต่อไป

    • GPU มือถือที่สืบสายมาจากตระกูล PowerVR มีฟังก์ชันแบบนั้น
      https://medium.com/pocket-gems/programmable-blending-on-ios-...
      https://developer.apple.com/videos/play/tech-talks/605
    • ครั้งล่าสุดที่ได้ลองแตะ GPU มือถือ PowerVR มี programmable blending และจริง ๆ แล้วมันเป็นวิธี blending เพียงแบบเดียวด้วย บน PS Vita การเปลี่ยน blend state ใช้เวลาประมาณ 1ms เลยดูไม่สวยนัก
    • คิดว่า VK_EXT_fragment_shader_interlock ก็น่าจะเป็น programmable blending แบบหนึ่ง DirectX ฝั่ง Raster-order-views ก็เช่นกัน
      มีตัวอย่างดี ๆ ที่ใช้สิ่งนี้: https://vulkan.org/user/pages/09.events/vulkanised-2024/vulk...
    • เดี๋ยวนี้มี mesh shader, work graphs, CUDA และ shader ภาษา C++ ทั่วไปด้วย OTOY ตอนนี้เรนเดอร์ทั้งหมดด้วย compute แล้ว
    • ส่วนใหญ่พวกนั้นน่าจะ emulate ได้ใน Vulkan หรือ DX12 ส่วน API อื่นไม่ค่อยแน่ใจ แต่สงสัยว่า กรณีใช้งาน จริงคืออะไร
      มองว่าพอจะ implement ได้ในระดับหนึ่ง แต่ถ้าไม่มี use case ที่น่าเชื่อถือ ก็คงยากที่จะให้เหตุผลรองรับงาน implement นี้
  • ส่วนที่ชอบที่สุดของ GS คือขนาดที่บ้าบอของ โครงสร้างบัส กว้างรวม 2560 บิต และการแบ่งแคชก็ฉลาดด้วย
    PS3 ในบางแง่รู้สึกเหมือนถอยหลัง โดยเฉพาะเรื่อง blending

  • อยากรู้ว่าแนวทางนี้เทียบกับ ubershader ของ Dolphin ได้อย่างไร

    • โดยพื้นฐานแล้วแทบไม่ใช่สิ่งที่จะเอามาเทียบกัน Dolphin ubershader ทำงานอย่างเดียวคือเลียนแบบ fixed-function blending/texturing ด้วยฮาร์ดแวร์ยุคใหม่ที่ยืดหยุ่น
      จริง ๆ ตอนที่ Dolphin นำมาใช้ เทคนิคนี้ก็เก่าอยู่แล้ว โปรเจกต์นี้เป็นเรนเดอเรอร์เต็มรูปแบบที่รวมถึง rasterizer และอย่างที่เห็นในบทความก็มี ubershader สำหรับ blending ด้วย
      shader ไม่ได้วาดสามเหลี่ยม แต่ถูกเรียกในแต่ละจุดภายในสามเหลี่ยม รับอินพุตบางอย่าง แล้วตัดสินสีของจุดนั้น คล้าย ๆ แบบเลือน ๆ กับการเทียบ emulator CPU ทั้งตัวกับสิ่งที่ implement แค่คำสั่ง ADD/MUL
  • สงสัยว่า top-left raster หมายถึงอะไร