AMD prozradilo roadmapy procesorů. Od základu nová architektura Zen 5 v roce 2024

10. 6. 2022

Sdílet

Ryzen 3 2200G s integrovaným GPU architektury Vega Autor: Fritzchens Fritz, použito se souhlasem autora – public domain
Ryzen 3 2200G s integrovaným GPU architektury Vega
AMD zveřejnilo plány procesorů pro desktop, notebooky i servery na rok 2023 a 2024. A také poprvé začíná mluvit o Zenu 5, úplně novém jádru, které by možná mohlo výrazně rozšířit architekturu a zvýšit IPC.

Z konference AMD Financial Day 2022, která proběhla včera, už jsme tu probrali to, co firma řekla nového k Zenu 4 a Ryzenům 7000 (zejména prozrazení IPC). Teď se podíváme na plány budoucích procesorů, tzv. roadmapy. Firma totiž prozradila tyto plány prakticky pro všechny segmenty trhu, a to po dlouhé době, kdy jsme od ní žádné roadmapy neviděli a byli jsme odkázáni jen na nejisté úniky.

Začneme celkovou roadmapou procesorových architektur – čímž se myslí samotná jádra, nikoliv ještě konkrétní procesory. AMD zatím ukázalo plán do roku 2024, v němž je Zen 4 a Zen 5. Zatím tedy ještě nemáme jistotu, že bude i Zen 6 (nejspíš ale bude).

Roadmapa architektur CPU Zen

Pro nás nová část roadmap začíná generací Zen 4. Již nějakou dobu víme, že Zen 4 bude mít „kompaktní“ verzi Zen 4c určenou pro cloudové servery. Ta bude použitá v procesorech Epyc 7004 Bergamo a bude, zdá se, obnášet menší L3 cache a asi i další úpravy za účelem zmenšení plochy a zvýšení energetické efektivity. Má však podporovat všechny instrukce, které umí plnotučný Zen 4 (což znamená i AVX-512).

Roadmapa ale nově potvrzuje, že vedle Zenu 4c a základního Zenu 4 bude existovat také Zen 4 s 3D V-Cache. Tato technologie tak bude pokračovat.

Druhá nová informace je o výrobním procesu. AMD v roadmapě říká, že Zen 4 bude vyráběný na 5nm procesu, ale vedle toho také na 4nm technologii. To je překvapení, protože Ryzeny 7000 i Epycy 7004 (jak Bergamo se Zenem 4c, tak Genoa se standardním Zenem 4) podle předchozích oficiálně sdělených informací jsou rozhodně 5nm.

AMD ale teď prozradilo, že mobilní verzi Zenu 4, což budou procesory Ryzen 7000 s kódovým označením „Phoenix Point“, bude vyrábět na 4nm procesu – zřejmě technologii N4 od TSMC. Toto není nějaká radikální změna, proces N4 je vylepšenou odvozeninou 5nm procesu N5 a je mezi nimi určitá kompatibilita. Ale znamená to, že tyto procesory budou benefitovat z o něco lepších vlastností křemíku.

Roadmapa CPU architektur AMD dle prezentace na Financial Analyst Day 2022 Roadmapa CPU architektur AMD dle prezentace na Financial Analyst Day 2022 (Zdroj: AMD)

Zen 5: velká architektonická změna

Tři verze architektury bude mít i další generace jader CPU – Zen 5. Také u něj nás čeká základní Zen 5, dále verze s 3D V-Cache a také jádro Zen 5c se zmenšenou plochou a zlepšenou efektivitou. To se opět asi objeví v cloudových serverových procesorech, ale je možné, že ho firma jednou použije také v lowendových procesorech navazujících na APU Mendocino, které půjde na trh letos a obsahuje zredukovanou verzi Zenu 2, která je možná trochu předobrazem Zenu 4c a 5c. A případně do hybridních big.LITTLE procesorů, pokud by je vyrábělo.

Procesory s jádry Zen 5 budou podle AMD vyráběné na 4nm a 3nm procesu. Opět je tu tedy mix technologií, ovšem zde je to závažnější detail, protože už nejde o deriváty stejné generace. 4nm/5nm proces a 3nm proces jsou dvě oddělené technologie rozdílných generací. Zatím nevíme, které procesory chce AMD vyrábět jakým procesem.

Pro Zen 5 je důležité, že opět půjde o velký upgrade architektury, dalo by se říct, že půjde o od základu nové jádro, byť to není úplně přesné, protože i tato nová jádra přebírají některé prvky a techniky z předchozích. AMD postupuje u jader linie Zen tak, že vždy v jednom jádru udělá takovéto velké změny a řadu částí navrhne nově nebo změní jejich koncepci. Po této „velké“ generaci pak následuje jádro, které používá stejnou základní koncepci, ale má vylepšené různé dílčí aspekty nebo věci, u nichž byl během vývoje předchozího jádra nalezen potenciál pro další zlepšení. Někdy asi může jí i o opravy chyb nalezených v předchozím jádru nebo o doimplementování funkcí, které měly být v původním jádru, ale opozdily se a nestihly uzávěrku. Tyto evoluční architektury by obvykle měly přinášet méně dramatické změny a menší nárůsty IPC.

Představitelem těch nových jader byl Zen 1 a Zen 3 a dalším bude právě Zen 5, proto toho od něj lze dost čekat. Naopak Zen 2 a Zen 4 představují ony evoluční architektury. V souladu s tím už AMD dříve sdělilo, že ačkoliv u Zenu 4 také předpokládá dobré výsledky, Zen 5 bude relativně větší událost než Zen 4. Mike Clark, jeden z šéfarchitektů vývoje jader Zen, před časem naznačil, že Zen 5 je podle něj zatím nejzajímavější generace, tak snad z tohoto „hype“ něco bude.

Architektura AMD Zen 5 dle prezentace na Financial Analyst Day 2022 Architektura AMD Zen 5 dle prezentace na Financial Analyst Day 2022 (Zdroj: AMD)

Změny v jádře: změny v pipeline, zaměření na vyšší IPC

Zatím firma ale řekla jen velmi málo k tomu, v čem bude Zen 5 inovativní a co se změní. Architektura má mít zlepšený výkon a energetickou efektivitu. To je víceméně povinná, automatická věc. A údajně má být optimalizovaná tak, aby vyhovovala pro širokou škálu úloh. To má zahrnovat i zlepšení výkonu v úlohách umělé inteligence a strojového učení – zřejmě se zase bavíme o dalších instrukčních rozšířeních specializovaných na AI výpočty, možná by mohlo jí o převzetí instrukcí Intel AMX nebo nějakou vlastní obdobu.

Nejzásadnější informace je prostřední odrážka v krátkém výčtu, který na slajdu vidíte, mluvící o „re-pipeliningu frontendu jádra a širokém issue“, jakkoli vágní to je. Co se pod tím míní? Frontend procesoru označuje tu část, která vykonává fetch instrukcí z L1 cache, jejich dekódování (v instrukčních dekodérech), což jsou zrovna ty části, které jsou ovlivněné komplikovaností instrukční sady x86. V těchto fázích pipeline CPU proto v jistých ohledech mají inženýři x86 procesorů nejtěžší práci. A spadá sem i prediktor větvení, další kritický faktor.

Re-pipelining by mohl znamenat, že se změní rozdělení práce do různých stupňů pipeline, a dokonce by se mohl změnit počet stupňů, což jsou právě ty dalekosáhlé změny prováděné v nových jádrech oproti evolučním architekturám. Pokud by AMD pipeline prodloužilo (přidalo stupně), mohlo by to zvýšit dosahované takty CPU. Pokud by se počet snížil, bude to mít opačný efekt, ale zase to také může zvýšit IPC. Z pipeline o nízkém počtu stupňů zřejmě hodně těží IPC například jader Cortex od ARMu.

Ona zmínka o „wide issue“ pak přímo ukazuje na to, že by Zen 5 měl být navržený za účelem zvýšeného IPC. AMD u Zenu 3 pod „Issue Width“ rozumělo to, kolik operací lze umístit v jednom cyklu do jeho vykonávacích jednotek backendu (ALU, AGU). Takže vypíchnutí šířky issue by zde mohlo znamenat, že AMD konečně přidá další jednotky – jádro by tak mohlo mít více než současné čtyři ALU v celočíselné části, mohly by přibýt load/store pipeline, takže by jádro zvládalo více operací s pamětí za jeden cyklus (Zen 3 podporuje maximálně tři). A mohl by být zvýšený i počet SIMD pipeline v FPU části. Více jednotek je obecně předpoklad pro vyšší IPC. Toto by tedy mohlo ukazovat, že Zen 5 půjde stejnou cestou širšího jádra s vyšším výkonem na 1 MHz jako architektury Applu nebo architektura Golden Cove od Intelu (P-Core procesorů Alder Lake).

Schéma architektury AMD Zen3 Schéma architektury AMD Zen 3. Termínem Issue Width AMD u Zenu 3 označovalo celkový počet ALU, AGU, jednotek v FPU a jednotek pro větvení, které může procesor špičkově zaměstnat µOpy ze schedulerů v jednom cyklu (Zdroj: AMD)

Zen 5 přijde až v roce 2024

Doteď se opatrně věřilo, že s trochou štěstí by Zen 5 mohl na trh přijít již na konci roku 2023, tedy zhruba rok po Zenu 4 (nové architektury totiž mohou vyjít po kratším čekání než ty evoluční – je to proto, že zatímco evoluční architektura je závislá na dokončení svého předchůdce, ona následující nová generace je částečně vyvíjená paralelně se svým evolučním předchůdcem). Nicméně Zen 4 vyjde až na podzim 2022 (ne začátkem léta jako Zen 2) a stáhnout interval na jediný rok zatím asi AMD nezvládne.

Nyní již bylo oficiálně potvrzeno, že procesory architektury Zen 5 vyjdou až v roce 2024, byť to může být třeba již v jeho první polovině (pokud by interval byl cca 18 měsíců, jako byl mezi Zenem 2 a Zenem 3).

Roadmapy procesorů: desktop

Kromě samotných architektur AMD ukázalo také roadmapy produktů, které na jádrech Zen 4 a 5 budou založené. Jako první se podíváme na desktop. Roadmapa ukazuje, že pro desktopový socket AMD chystá běžné Ryzeny 7000 s architekturou Zen 4 (ty mají kódové označení Raphael, zde neuvedené) i procesory s 3D V-Cache. Ne v materiálech od firmy, ale v neoficiálním úniku se objevily nějaké zmínky, že by v této generaci již i mohlo jít o více modelů než jen jediné osmijádro pro hráče, jako to je teď v generaci Zen 3 s Ryzenem 7 5800X3D.

Procesory AMD Ryzen 7000 pro desktop prezentace na Financial Analyst Day 2022 Procesory AMD Ryzen 7000 pro desktop, prezentace na Financial Analyst Day 2022 (Zdroj: AMD)

Roadmapa ale také ukazuje, že AMD plánuje Ryzen Threadripper 7000 s architekturou Zen 4 (ale už bez zmínky o 3D V-Cache). Asi také není jisté, zda se tím myslí běžný levnější Threadripper, dražší Threadripper Pro, nebo obojí.

Méně toho AMD chce prozradit k následující generaci založené už na Zenu 5. Zatím jsou vyznačené jen jedny procesory – s kódovým označením Granite Ridge. Toto jméno už známe, takže se zdá, že tento únik byl pravdivý. Podle něj by Granite Ridge měly být výkonné procesory pro socket AM5, které budou vydané pod označením Ryzen 8000.

Roadmapa procesorů AMD Ryzen a Ryzen Threadripper pro desktop a pracovní stanice dle prezentace na Financial Analyst Day 2022 Roadmapa procesorů AMD Ryzen a Ryzen Threadripper pro desktop a pracovní stanice dle prezentace na Financial Analyst Day 2022 (Zdroj: AMD)

AMD teď uvádí jen to, že budou založené na „pokročilém výrobním procesu“. Není tedy jasné, zda je pořád v plánu 3nm proces, nebo se AMD rozhodlo tyto procesory převést na jistější 4nm technologii. Ryzeny 8000 Granite Ridge by asi měly vyjít v roce 2024. Threadrippery 8000 zde zatím uvedené nejsou, což může znamenat, že AMD je stihne vydat až v roce 2025. Ale také nemusí, možná je jen zatím nechce takto oznámit.

Tento plán neukazuje kompletní desktopovou roadmapu, ale jen desktopové procesory „s vysokým výkonem“. Nejsou v něm tedy levnější procesory pro socket AM5, jako například APU, která by měla být odvozená od notebookových procesorů, jejichž roadmapu probereme nyní. Nicméně AMD na Financial Analyst Day víceméně ignorovalo oblast nejlevnějších procesorů, jako bude například nedávno oznámený mobilní SoC Mendocino. To, co je zde ukázané, není proto všechno, co bude firma v budoucnu prodávat, ale jen to, čím se nejvíc chce chlubit.

Socket AM5 Socket AM5, do kterého se budou instalovat desktopové procesory Ryzen s jádry Zen 4 a Zen 5 (Zdroj: AMD)

Ryzen 7000 a 8000 pro notebooky

Notebooková roadmapa nám chyběla asi nejvíc, protože AMD v poslední době nic nepotvrzovalo dopředu, letošní Ryzeny 6000 tak byly až do vydání známé jen z úniků. Teď ale AMD potvrdilo příští dvě generace. Zřejmě na rok 2023 se chystají procesory Phoenix Point. To by patrně měly být mobilní Ryzeny 7000. Phoenix Point bude mít kromě jader Zen 4 také integrovanou grafiku již s novou architekturou RDNA 3 a AMD potvrdilo, že bude používat 4nm výrobní proces, na rozdíl od desktopového Ryzenu 7000.

Následovat bude rovnou generace s architekturou CPU Zen 5. Ta má být vyráběná „pokročilým procesem“, takže zatím nevíme, jestli bude 3nm. Tyto procesory by asi měly být uvedené pod označením Ryzen 8000 a jejich kódové označení je Strix Point. Opět se tu potvrzuje 13 měsíců starý únik. Ten tehdy také uváděl, že Strix Point bude big.LITTLE – možná by mohl mít malá jádra Zen 4c. Ale to AMD zatím neuvádí a píše jen Zen 5. Grafika má být „RDNA 3+“ (vylepšená verze RDNA 3?).

Roadmapa procesorů AMD Ryzen pro notebooky dle prezentace na Financial Analyst Day 2022 Roadmapa procesorů AMD Ryzen pro notebooky dle prezentace na Financial Analyst Day 2022 (Zdroj: AMD)

Mimochodem, AMD má zřejmě lehký chaos v pojmenováních – nedávno totiž separátně odhalilo roadmapu výkonných mobilních procesorů pro herní notebooky a tyto čipy v ní označovalo jen „Phoenix“. Pod tímto označením také už dávněji figurovaly v neoficiálních drbech – opět tedy asi potvrzení pravdivosti staršího úniku. Roadmapa pro herní notebooky také navíc uvádí procesory Dragon Range, které zde nejsou. Dragon Range by měly být notebookovou verzí Ryzenů 7000 pro desktop.

Roadmapa procesorů AMD Ryzen na rok 2022 a 2023 q1 2022 Roadmapa procesorů AMD Ryzen 7000 na rok 2022 a 2023 ukázaná při ohlášení finančních výsledků za Q1 2022 (Zdroj: AMD, via: Tom's Hardware)

Již Ryzen 7000 Phoenix Point a poté i Ryzen 8000 Strix Point mají uvedenou ještě jednu novinku: „AIE“. To by mělo znamenat AI Engine, jde o specializovaný akcelerátor neuronových sítí, asi podobný tensor jádrům Nvidie, a snad by mohl vycházet z technologií Xilinxu (nebo aspoň tato technologie nyní byla prezentována jako část AI strategie divize Xilinx).

Serverové procesory: Genoa s 96 jádry Zen 4 v Q4 2022

Roadmapa serverových procesorů bude hodně košatá. AMD, zdá se, chystá čtyři různé verze serverových procesorů s architekturou Zen 4. Tři z nich by měly používat stejný socket SP5 s dvanáctikanálovým řadičem pamětí DDR5. Základní verzi už známe delší dobu – Epyc 7004 „Genoa“ bude mít až 96 jader Zen 4 a také podporu PCIe 5.0 a CXL.

AMD teď potvrdilo, že vydání těchto procesorů má být ještě před koncem roku 2022, někdy ve čtvrtém kvartálu (Q4 2022). Vyjdou tedy poměrně krátce po (opožděné) nové generaci Xeonů Sapphire Rapids od Intelu, na což jsme naráželi v tomto článku.

AMD Epyc 7004 Genoa dle prezentace na Financial Analyst Day 2022 AMD Epyc 7004 Genoa dle prezentace na Financial Analyst Day 2022 (Zdroj: AMD)

AMD se dopustilo i jednoho benchmarku: Epyc 7004 Genoa má údajně dosahovat o víc než 75 % lepšího výkonu ve vybrané enterprise Java úloze. Nicméně berte to zatím s rezervou, oficiální benchmarky mohou být selektivní a reprezentovat spíše ideální než typické scénáře.

Cloudový Epyc Bergamo: Zen 4c má stále SMT i AVX-512

Do stejného socketu a desek se bude dát nainstalovat ještě verze s lehčími jádry Zen 4c, již zmíněný Epyc 7004 „Bergamo“, který díky úspornější architektuře má mít až 128 jader a 256 vláken (jádro Zen 4c tedy neztratilo SMT), ale zachovanou podporu všech instrukcí a funkcí z procesorů Genoa. Tudíž při jeho použití se změní jen hrubý výkon a bude zachovaná 100% kompatibilita softwaru.

AMD Epyc 7004 Bergamo dle prezentace na Financial Analyst Day 2022 AMD Epyc 7004 Bergamo dle prezentace na Financial Analyst Day 2022 (Zdroj: AMD)

Tyto procesory mají jít na trh (být fyzicky dostupné) v první polovině roku 2023.

Genoa-X: Přes 1 gigabajt 3D V-Cache

Vedle těchto dvou variant AMD teď oznámilo dvě další. První je Epyc 7004 „Genoa-X“, která používá jádra Zen 4 s 3D V-Cache navíc. Je to tedy pokračování Epyců 7003 „Milan-X“. AMD uvádí, že Genoa-X bude mít také 96 jader Zen 4 a více než 1 GB celkové L3 Cache na jeden procesorový socket.

Asi by to mohlo znamenat, že výchozí verze Zenu 4 bude mít opět 32 MB L3 cache na každý CPU čiplet s osmi jádry a čiplet s 3D V-Cache by mohl obsahovat 64 MB navíc. Protože CPU čipletů je 12, dávalo by to dohromady 1152 MB L3 cache.

Tyto procesory mají vyjít někdy v roce 2023 – AMD neříká přesně, kdy. Jejich velká cache s vysokou propustností má být užitečná pro technické (CAD/CAM) a vědecké (HPC) výpočty, ale také pro databáze.

AMD Epyc 7004 Genoa X a Siena dle prezentace na Financial Analyst Day 2022 AMD Epyc 7004 Genoa-X a Siena dle prezentace na Financial Analyst Day 2022 (Zdroj: AMD)

Siena: levnější platforma SP6?

Nyní ale AMD také přišlo s dosud neznámou novinkou: vedle předchozích procesorů pro platformu s 12kanálovými pamětmi byla oznámena levnější verze 5nm Epyců s kódovým označením Siena. Zde už to možná nebudou Epycy 7004, ale jméno by mohlo být třeba Epyc 5004 (to ale jenom hádáme).

Procesory Siena budou mít plnotučná jádra Zen 4, ale v počtu maximálně 64. Tyto procesory mají používat levnější platformu. Současné Epycy 7002 a zejména 7003 mají problém s pokrytím levnějších serverů, což asi právě Siena má řešit. Bude zřejmě použitý levnější socket – možná, že jde o socket SP6, který se objevil v únicích. Podle těch má podporovat jen šestikanálové paměti DDR5 a menší počet linek PCI Express 5.0 než velký socket SP5. Procesory Siena budou asi mít nižší TDP, také možná nebudou umět 2S konfiguraci, ale jen 1S, a desky pro ně by asi měly být celkově levnější. Uvidíme, zda třeba na této verzi Epyců 7004 nebudou založené ony Threadrippery 7000.

Vydání procesorů Siena má také být někdy v roce 2023 bez bližšího upřesnění. Podle AMD by měly být určené například pro použití v telekomunikační infrastruktuře nebo v embedded a „edge“ serverech.

Zen 5 v serverech již v roce 2024

A úplně nakonec: AMD oznámilo (respektive prozradilo v roadmapě) také pátou generaci serverových procesorů Epyc, tedy Epyc 7005. Bohužel bez větších podrobností, takže nevíme, jestli bude použitý 3nm výrobní proces. AMD uvádí, že tato generace má kódové označení „Turin“ (všechna jména pro serverové generace jsou vždy podle italských měst, jak jste si asi všimli). Turin by se asi mohla jmenovat základní verze, tedy následník procesorů Genoa. Opět asi bude existovat také Turin-X a vedle toho nějaká cloudová a levnější verze, ale to AMD zatím nespecifikuje.

Cyber25

Roadmapa procesorů AMD Epyc pro servery dle prezentace na Financial Analyst Day 2022 Roadmapa procesorů AMD Epyc pro servery dle prezentace na Financial Analyst Day 2022 (Zdroj: AMD)

Epycy 7005 Turin by prý měly být uvedené ještě před koncem roku 2024, tedy do dvou let od uvedení Epyců 7004 s architekturou Zen 4. Je ale opět možné, že ony specializované deriváty opět vyjdou třeba až v průběhu roku 2025.

Zdroje: AMD (1, 2), AnandTech

Autor článku

Redaktor portálu Cnews.cz. Zaměřuje se na procesory, mobilní SoC, grafické karty, disky a další počítačový hardware. Profil autora →

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }
'; document.getElementById('outstream-iframe').onload = function () { setupIframe(); } replayScreen = document.getElementById('iinfoOutstreamReplay'); iinfoOutstreamPosition = document.getElementById('iinfoOutstreamPosition'); outstreamContainer = document.getElementsByClassName('outstream-container')[0]; setupReplayScreen(); } function setupIframe() { outstreamDocument = document.getElementById('outstream-iframe').contentWindow.document; let el = outstreamDocument.createElement('style'); outstreamDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:-5px;right:25px}"; videoContent = outstreamDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; if ( location.href.indexOf('rejstriky.finance.cz') !== -1 || location.href.indexOf('finance-rejstrik') !== -1 || location.href.indexOf('firmy.euro.cz') !== -1 || location.href.indexOf('euro-rejstrik') !== -1 || location.href.indexOf('/rejstrik/') !== -1 || location.href.indexOf('/rejstrik-firem/') !== -1) { outstreamDirectPlayed = true; soundAllowed = true; iinfoVastUrlIndex = 0; } if (!outstreamDirectPlayed) { console.log('OUTSTREAM direct'); setUpIMA(true); } else { if (soundAllowed) { const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('OUTSTREAM sound allowed'); setUpIMA(false); }).catch(function () { console.log('OUTSTREAM sound forbidden'); renderBanner(); }); } } else { renderBanner(); } } } function getWrapper() { let articleWrapper = document.querySelector('.rs-outstream-placeholder'); // Outstream Placeholder from RedSys manipulation if (articleWrapper && articleWrapper.style.display !== 'block') { articleWrapper.innerHTML = ""; articleWrapper.style.display = 'block'; } // Don't render OutStream on homepages if (articleWrapper === null) { if (document.querySelector('body.p-index')) { return null; } } if (articleWrapper === null) { articleWrapper = document.getElementById('iinfo-outstream'); } if (articleWrapper === null) { articleWrapper = document.querySelector('.layout-main__content .detail__article p:nth-of-type(6)'); } if (articleWrapper === null) { // Euro, Autobible, Zdravi articleWrapper = document.querySelector('.o-article .o-article__text p:nth-of-type(6)'); } if (articleWrapper === null) { articleWrapper = document.getElementById('sidebar'); } if (!articleWrapper) { console.error("Outstream wrapper of article was not found."); } return articleWrapper; } function setupDimensions() { outstreamWidth = Math.min(iinfoOutstreamPosition.offsetWidth, 480); outstreamHeight = Math.min(iinfoOutstreamPosition.offsetHeight, 320); } /** * Sets up IMA ad display container, ads loader, and makes an ad request. */ function setUpIMA(direct) { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); if (direct) { adsRequest.adTagUrl = directVast; console.log('Outstream DIRECT CAMPAING advert: ' + directVast); videoContent.muted = true; videoContent.volume = 0; outstreamDirectPlayed = true; } else { adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Outstream advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; } // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = outstreamWidth; // adsRequest.linearAdSlotHeight = outstreamHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function setupReplayScreen() { replayScreen.addEventListener('click', function () { iinfoOutstreamPosition.remove(); iinfoVastUrlIndex = 0; outstreamInit(); }); } /** * Sets the 'adContainer' div as the IMA ad display container. */ function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. outstreamDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( outstreamDocument.getElementById('adContainer'), videoContent); } function unmuteAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } } /** * Loads the video content and initializes IMA ad playback. */ function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(outstreamWidth, outstreamHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } /** * Handles the ad manager loading and sets ad event listeners. * @param { !google.ima.AdsManagerLoadedEvent } adsManagerLoadedEvent */ function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } /** * Handles actions taken in response to ad events. * @param { !google.ima.AdEvent } adEvent */ function onAdEvent(adEvent) { // Retrieve the ad from the event. Some events (for example, // ALL_ADS_COMPLETED) don't have ad object associated. const ad = adEvent.getAd(); console.log('Outstream event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: // This is the first event sent for an ad - it is possible to // determine whether the ad is a video ad or an overlay. if (!ad.isLinear()) { // Position AdDisplayContainer correctly for overlay. // Use ad.width and ad.height. videoContent.play(); } outstreamDocument.getElementById('adContainer').style.width = '100%'; outstreamDocument.getElementById('adContainer').style.maxWidth = '640px'; outstreamDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); // This event indicates the ad has started - the video player // can adjust the UI, for example display a pause button and // remaining time. if (ad.isLinear()) { // For a linear ad, a timer can be started to poll for // the remaining time. intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } outstreamDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (outstreamLastError === 303) { if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } } break; case google.ima.AdEvent.Type.COMPLETE: // This event indicates the ad has finished - the video player // can perform appropriate UI actions, such as removing the timer for // remaining time detection. if (ad.isLinear()) { clearInterval(intervalTimer); } if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } break; } } /** * Handles ad errors. * @param { !google.ima.AdErrorEvent } adErrorEvent */ function onAdError(adErrorEvent) { // Handle the error logging. console.log(adErrorEvent.getError()); outstreamLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { renderBanner(); } } function renderBanner() { if (isBanner) { console.log('Outstream: Render Banner'); iinfoOutstreamPosition.innerHTML = ""; iinfoOutstreamPosition.style.height = "330px"; iinfoOutstreamPosition.appendChild(bannerDiv); } else { console.log('Outstream: Banner is not set'); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoOutstreamPosition.remove(); outstreamInit(); } else { return false; } adVolume = 1; return true; } /** * Pauses video content and sets up ad UI. */ function onContentPauseRequested() { videoContent.pause(); // This function is where you should setup UI for showing ads (for example, // display ad timer countdown, disable seeking and more.) // setupUIForAds(); } /** * Resumes video content and removes ad UI. */ function onContentResumeRequested() { videoContent.play(); // This function is where you should ensure that your UI is ready // to play content. It is the responsibility of the Publisher to // implement this function when necessary. // setupUIForContent(); } function onActiveView() { if (outstreamContainer) { const containerOffset = outstreamContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (outstreamPaused) { adsManager.resume(); outstreamPaused = false; } return true; } else { if (!outstreamPaused) { adsManager.pause(); outstreamPaused = true; } } } return false; } let outstreamInitInterval; if (typeof cpexPackage !== "undefined") { outstreamInitInterval = setInterval(tryToInitializeOutstream, 100); } else { const wrapper = getWrapper(); if (wrapper) { let outstreamInitialized = false; window.addEventListener('scroll', () => { if (!outstreamInitialized) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { outstreamInit(); outstreamInitialized = true; } } }); } } function tryToInitializeOutstream() { const wrapper = getWrapper(); if (wrapper) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { if (cpexPackage.adserver.displayed) { clearInterval(outstreamInitInterval); outstreamInit(); } } } else { clearInterval(outstreamInitInterval); } } }
OSZAR »