text:
Libya: Bewitched, bothered and bewildered By William Bowles
"Despite the situation in Libya remaining unresolved, one thing is now certain: the president of the United States is now in control of the money, and this gives him a powerful tool … 'Most countries consider the freezing of their assets an act of economic warfare'" — 'Money as a weapon in West's war on Libya', RT, 7 March 2011
In the West, revolution is something we are not very familiar with although it's something the Left talk about an awful lot, other peoples' revolutions that is.
But exactly what is a revolution and would we know one if it ran over us? Judging by the reactions to events in the Middle East / North Africa, the answer has to be a resounding no.
For confirmation of this view we need only look at the various stories coming from the 'left' especially those on Libya, urging revolution and the removal of Ghadafi.
Ghadafi is a product of the post-war anti-colonial movements that swept Africa during the 1960s and firmly in the Nasser 'mould'; nationalist, anti-colonial but also anti-communist, preferring instead his so-called Third Way, what he finally referred to as 'popular capitalism', whatever that is.[1]
Be that as it may, until 9/11 Ghadafi supported what he regarded as anti-colonial movements in Northern Ireland and elsewhere, though one has to ask the question: what was the rationale behind Ghadafi's involvement in struggles so far removed from his own? But as they say, 'talk is cheap' and undoubtedly Ghadafi was targeting a specific faction of the Western Left for support (at one point in the late 1980s even I got invited to Libya on a 'fact-finding' mission, an invitation I declined).
The uprising / coup in Libya is being embraced by the Left, viewing it as a continuation of the struggles elsewhere in the Middle East and North Africa. But from its inception it was obvious that it didn't follow the pattern established elsewhere, not that this makes it any the less legitimate but it does mean that very different forces were and undoubtedly still are at work in Libya.
In reality therefore and unlike Egypt for example, we are clueless about the nature of the opposition. Who are they? What do they want (aside from removing Ghadafi)?
"[D]espite various defections — including those by ministers, diplomats, military officers, and air force pilots — we have yet to see the collective decision on the part of the Libyan armed forces to champion the demands of protesters. In fact, there is little indication of whether the Libyan armed forces have the institutional capacity for disciplined collective action. . . ." — 'International Intervention in Libya: A Documentary Remix' By VJ Um Amel, MRZine, 7 March 2011
In the beginning of the Libyan uprising the headlines on the Left were full of praise and support for the insurrectionaries, after all wasn't Ghadafi an autocratic and corrupt leader who had finally gotten his marching orders from the masses?
But these are forces about which we know almost nothing, made all the more complicated by the fact that there appears to be more than one group claiming leadership of the insurrection (at least three at the last count, or are they factions? Who knows? All the more reason to stay out of it). And unlike Egypt this is an insurrection that may well have been sparked by the youth and the poor but it is led by the intelligentsia, academics and businessmen. And these are the same people who are calling for airstrikes and a 'no-fly zone'. Not exactly what I'd call a revolutionary act. To be accurate, there is also another group of insurrectionaries who most definitely oppose any kind of foreign intervention but what is the relationship between all these groups? Are they in competition for power? For leadership? Who knows…?
It's obvious that the Empire has designs on Libya and its vast oil reserves (aside from the possibility of establishing a NATO / AFRICOM bridgehead in North Africa), this explains their rush to deliver 'humanitarian assistance' and talk of Ghadafi's 'genocide'. Unlike Egypt or Tunisia, where there were no calls for intervention, sanctions or 'no-fly zones' from the West, from day one of the Libyan 'revolution' the West went on the offensive against Ghadafi, freezing Libyan assets and using the International Criminal Court to investigate the allegations of war crimes committed by Ghadafi, followed by overt threats of invasion unless Ghadafi stepped down.
And today we learn that the US has asked Saudi Arabia to supply the rebels with weapons including antitank rockets and anti-aircraft missiles which if it comes to pass, serves only to escalate and prolong the struggle. And once more it will be the people who pay the price for Western interference. In addition the UK government aside from its incompetent and botched SAS incursion now informs us that it has the Black Watch army group on standby to intervene. Will these fools never learn, especially the tin-pot British variety which is clearly well past its sell-by date?[2]
The Left and Libya
The very real possibility of direct (or even indirect) Western intervention presented the Western Left with a very real conundrum: How is it possible to support the insurrection whilst at the same time opposing Western intervention, especially when at least one faction (or the leaders) of the rebels is calling for the West to intervene?
On the surface, the answer is obvious: No to intervention – Yes to revolution! And this is pretty much what the progressive media has been saying but it creates a very real dilemma for the left. How can we oppose intervention without supporting, even if reluctantly, Ghadafi, especially now that the West has intervened? And it's a dilemma that found both Castro and Chavez apparently supporting Ghadafi and for which they got a lot of flack from the Western left (not to mention a lot of confused expressions).
So why did Chavez and Castro (as well as Daniel Ortega of Nicaragua) offer public support to Ghadafi? Well, as things have turned out, it is clear that this is not about Ghadafi but all about imperial ambitions and I hazard the guess that they both knew more about the machinations of the Empire than do an entire Tahrir Square-full of Western lefties.
Stick with what you know
I'm almost clueless about domestic Libyan politics aside from Libya's role in the global rule of capital but with almost as many 'guest workers' as native Libyans, a developed West and an undeveloped East, tribal politics and Islam, it's definitely a heady mix, best left to the Libyans to sort out for themselves.
(One) of the problems the (Western) left has is that it's calling for support for the insurrectionaries without a clue as to who they are or what they want. It's almost a knee-jerk reaction when what was really needed from the very beginning was the call for the Empire to stay the fuck out of it and let the Libyans get on with whatever it is they are trying to do! (Clearly this is a trait (interfering that is) that the Empire and the Western Left share in common).
As with the other insurrections currently underway there are none of the traditional 'markers' that would point in the general direction of a genuine revolution led from the Left. It's not even clear that a Left of some substance exists in Libya let alone an organized working class such as Egypt has and which formed the backbone of the Egyptian insurrection.
Cut adrift from all the traditional hallmarks of class struggle as it was once waged in times gone by, the Western Left is hanging on to events by the skin of its teeth, much in the way the Empire is reacting to these (potentially) momentous events but unlike the Barbarians the Left just can't make up its mind about which side it's on.
Judging by the videos I've seen and the reports I've read, especially in the MSM, it would appear that the entire country hates Ghadafi but clearly this is not true, it's just not clear how the country is divided and what percentage are prepared to take up arms in order to prevail. All the more reason why any interference by anybody can only result in disaster for the Libyan people.
"For anyone harbouring any doubts, about the inevitable military intervention that shall occur in Libya, the AP news agency, which I consider to be well-informed, headlined a cable printed today which stated: "The NATO countries are drawing up a contingency plan taking as its model the flight exclusion zones established over the Balkans in the 1990s, in the event that the international community decides to impose an air embargo over Libya, diplomats said"." — 'NATO's Inevitable War: The Flood of Lies regarding Libya' by Fidel Castro, 4 March 2011, Global Research
But I fear that the damage has already been done, the wolf is at the door and huffing and puffing…
1. See 'The Libyan labyrinth' By Vijay Prashad for an excellent, if abbreviated account of Ghadafi's 'Green Revolution'.
2. The MSM's take on this ludicrous and extremely dangerous and provocative escapade is worth perusing. This from Channel 4 News' daily email shot:
The shambolic MI6/S[A]S "all because the lady loves milk tray" epic in the Libyan desert (suburbs of Benghazi) has caused a great deal of embarrassment to Foreign Secretary Hague who has just had to put up with a mauling in the Commons over it.
He's described it as a 'misunderstanding' but it's still very unclear what on earth was going on. Any self respecting FCO Arabist would never have entered a country in this way – black jump suits, weapons, and a helicopter landing at the dead of night. All the signs are that there was something else in play – whether an attempt to rescue somebody or retrieve a piece of real estate, all remains mere speculation. Will we ever know?
Failed SBS op 'won't destroy UK relations with rebels'
Postscript to the MI6/SAS debacle: A story in the UK Sun newspaper reveals all 'Brit held with SAS in Libya was spy'. Clearly, the Sun is well up on Channel 4.
Posted in: Essays | Tagged: castro, chavez, Ghadafi, intervention, Libya, NATO, no-fly zone, Saudi Arabia, War
Civil war in Libya, intervention by the West already a reality By William Bowles
Libya: Keeping up appearances By William Bowles
4 thoughts on "Libya: Bewitched, bothered and bewildered By William Bowles"
Pingback: Bewitched, bothered and bewildered By William Bowles « Dandelion Salad
Clark says:
"And today we learn that the US has asked Saudi Arabia to supply the rebels with weapons including antitank rockets and anti-aircraft missiles"
Got a link for this, please?
Also, I suggest you liaise with Duncan McFarlane. He's been looking at this, and he collects a lot of good links, too. I'll post something similar on his blog:
http://inplaceoffear.blogspot.com/2011/02/libya-most-libyans-dont-want-any.html
I hope you've looked at Craig Murray's piece:
http://craigmurray.org.uk/archives/2011/03/this-hague-cock-up-must-be-explained/
InI says:
Here's the link. It's a Robert Fisk piece
http://www.shoah.org.uk/2011/03/07/americas-secret-plan-to-arm-libyas-rebels/


text:
Eggs, basket: The hidden and not-so-hidden risks for companies that invest in bitcoin
thedig.substack.com
Betting on bitcoin seemed like a great idea for MicroStrategy. And then bitcoin dropped again.
This article is by guest author Michael Rapoport. Michael is a business and financial journalist who specializes in stories about accounting, banking, and financial regulation and is a former reporter for The Wall Street Journal. His work has appeared recently in Institutional Investor, Quartz, and Business Insider. Michael is on Twitter as @rapoportmike.
So far, betting on bitcoin has seemed like a great idea for MicroStrategy. The business-software company invested about $1.1 billion last year in bitcoin, and those holdings are now worth more than $2.2 billion, thanks to bitcoin's explosive market surge. MicroStrategy's stock has more than quadrupled since it announced its first bitcoin purchase last August.
Betting on bitcoin has also been a bad idea for MicroStrategy's earnings. The company's bitcoin investment dragged it into loss territory for the third quarter and first nine months of 2020 rather than posting profits.
How can both things be true? Because when it comes to bitcoin, reward and risk might as well exist in different universes. No one focusing on one wants to acknowledge the existence of the other. Bitcoin's price has surged to undreamt-of heights in recent months, but it also has a history of stunning declines — and that volatility, even if temporary, could be damaging to a company's balance sheet and earnings.
MicroStrategy is one of a still-small but growing number of companies placing bets on bitcoin and other digital currencies. Those moves have a degree of logic behind them, and certainly the potential rewards are tempting. But they'd better keep in mind that bitcoin has the potential to bite them, too, and not just in the obvious ways.
MicroStrategy has been by far bitcoin's biggest fan among public companies. The company said last summer that it would put most of its excess capital into bitcoin — it even sold $650 million in convertible notes in December specifically to raise money to buy more bitcoin. The $1.1 billion it's spent on bitcoin far outstrips all its other assets combined. Chief Executive Michael Saylor calls bitcoin "a battery charged with monetary energy." (The company declined to comment for this story.)
Others have followed. Payments company Square indicated in October it would invest $50 million, calling cryptocurrency "an instrument of economic empowerment." (Square couldn't be reached for comment.) Big-name investors like Paul Tudor Jones, Stanley Druckenmiller, and insurance company MassMutual have recently invested in bitcoin as well.
"Obviously some companies are excited about it," Matthew Schell, a Crowe LLP partner who co-chairs an American Institute of CPAs working group on digital assets. "While still not mainstream, it's going there."
MicroStrategy's Saylor has turned into a leading evangelist for bitcoin. He's holding a two-day online event in February for other companies interested in investing in bitcoin. He's publicly encouraged Elon Musk to move Tesla's resources into bitcoin, and the Tesla CEO didn't dismiss the possibility out of hand (though Musk has also tweeted negatively about bitcoin).
Elon Musk @elonmusk
Bitcoin is almost as bs as fiat money
10,370 Retweets141,596 Likes
It's easy to understand why MicroStrategy and others want to invest in bitcoin. Most companies keep their cash in ultra-safe, highly liquid instruments like Treasury bills, but right now that's effectively a recipe for losing money: Interest rates are close to zero, so a company's cash loses purchasing power as prices rise. If bitcoin's value keeps soaring and you can get better returns there, why not at least think about it?
Saylor calls bitcoin "an attractive investment asset with more long-term appreciation potential than holding cash." Hard to argue with that, thus far — MicroStrategy says it paid an average price of $15,964 for each of its bitcoins, and one bitcoin now trades for more than $32,000, as of Thursday's New York close.
But bitcoin's volatility also makes it an enormously risky bet — arguably a bet that prudent public companies don't want to make with the bulk of their cash. One bitcoin may be worth $32,000 now, but it was below $5,000 as recently as last March, and its value took stomach-turning drops in 2017 and 2019.
By the time this newsletter had been set-up late on Thursday, the price of bitcoin had dropped below $30,000.
Saylor calls bitcoin "a dependable store of value," but how can that be the case when the price is so volatile?
And while most other companies venturing into bitcoin are just dipping a toe in the water — Square's $50 million is less than 1% of its total assets, for instance — Saylor has done a cannonball into the deep end of the pool with his concentration of most of MicroStrategy's available cash in bitcoin.
It's like walking into a casino and betting all your chips on red at the roulette wheel, time after time: You might win for a while, but sooner or later, chances are pretty good you're going to lose, and maybe lose it all.
It's also worth remembering Saylor's history: In 2000, Saylor settled Securities and Exchange Commission allegations that MicroStrategy inflated its earnings by recognizing revenue too quickly. Saylor agreed to return $8.3 million to investors and pay a $350,000 fine; he didn't admit or deny wrongdoing, and he hasn't been accused of any impropriety regarding his investment in or promotion of bitcoin. (Notably, the SEC settlement didn't bar Saylor from being an officer or director of a public company, as such settlements sometimes do — so he was able to remain CEO of MicroStrategy.)
Bitcoin's fans argue it's more stable than it used to be. The recent investments from mainstream sources have helped make it more "respectable," they say. The regulatory guidelines for cryptocurrencies are clearer now, and the trading platforms are more reliable and established — you can buy bitcoin via PayPal.
Maybe so — but the volatility isn't just a thing of the past. Just this month, bitcoin's price has zigzagged wildly; it's fallen more than 20% in the past two weeks. Some believe it might be subject to manipulation: Bitcoin's price "is nearly certainly a bubble and likely manipulated. Investors should proceed with extreme caution," said Alex Pickard, a vice president of research at Newport Beach, Calif., investment-strategy firm Research Affiliates, in a recent blog post.
And that's just the obvious risk.
Despite bitcoin's rise in value, MicroStrategy also had to take a $44.2 million impairment charge on its bitcoin investment in the third quarter that ended Sept. 30. That dragged the company to a loss of $14.2 million for the quarter, and a loss for the first nine months of 2020 as well. (Of course, the company's non-GAAP numbers, which exclude the impairment, still show profits.)
Here's why: Under U.S. accounting rules, bitcoin and other cryptocurrencies aren't treated as cash or financial instruments. They're considered "indefinite-lived" intangible assets. Companies must evaluate them periodically to determine if their value has declined — and if they have, the companies must take an impairment charge to write them down, cutting into earnings. Notably, the same isn't true when they rise in value — under the rules, companies are supposed to record gains in value on digital currencies only when they're sold. (The rules are somewhat different for investment companies.)
"There is a potential for impairments, definitely," Schell said. "If you determine that fair value is below your cost basis, you're going to land in a place where you have an impairment."
That's what happened at MicroStrategy. The company paid an average price of $11,111 each for its initial $425 million investment in bitcoin, but bitcoin's trading price slipped as much as 9% below that level in early September, before it began its recent dramatic rise. That means an impairment charge was required .
MicroStrategy has acknowledged the risk of impairments that could hurt earnings. Phong Le, the company's chief financial officer, said during MicroStrategy's third-quarter earnings conference call that "negative swings in the market price of bitcoin could have a material impact on our GAAP earnings."
MicroStrategy has also added nearly a page and a half of risk factors about its bitcoin investment to its SEC filings, including impairment charges, a possible loss of liquidity, and, most of all, the potential for a drop in bitcoin's price to hurt MicroStrategy's own stock price, given the scale of the company's bitcoin investment.
A big bitcoin price drop could lead to "a more pronounced impact on our financial condition than if we invested our cash in a more diverse portfolio of treasury assets," the company said.
For Square's part, bitcoin's price has been on a sharp upward trend since the company invested in it, so Square hasn't faced an impairment charge, yet. The company's investment came near the start of the fourth quarter of 2020, and it hasn't yet issued a balance sheet that includes its bitcoin.
The number of public companies who've indicated they've invested in bitcoin is still tiny. In fact, there are probably more companies that have sprung up involved in bitcoin mining or trading than there are companies willing to bet their own money on it. In fact, a lot of companies in the bitcoin arena seem reluctant to eat their own cooking: Many bitcoin miners and traders haven't invested in bitcoin themselves .
And any missteps in accounting for or disclosing a bitcoin investment properly could draw scrutiny from the SEC. That's the case even though the commission seems disinclined to go after bitcoin broadly — as The Dig recently noted, the SEC isn't likely to pursue action against bitcoin or other cryptocurrencies that are acting as currencies rather than securities and have decentralized models, since no one organization would benefit from a spike in the currency's price.
For instance, the SEC sent a comment letter last May to Nukkleus, a tiny financial software company that owned digital currencies at one point. The commission asked why Nukkleus appeared to be accounting for them different from other companies, and directed the company to disclose more.
Nukkleus seems to have ignored the SEC's letter and its follow-ups — the SEC told the company in August that "you have not provided a substantive response." (Nukkleus couldn't be reached for comment. In its annual report filed in December, Nukkleus did add two pages detailing "cryptocurrency-related risks" and said it no longer held any digital currencies.)
Investing in bitcoin seems like the easiest of easy money these days, and certainly companies are going to continue to be attracted to the prospect of making big returns on their cash holdings. But this boomlet of corporate bitcoin investing has happened as bitcoin's price keeps going up — let's see what happens when that's not the case.
Because any potential investors need to be conscious of the risks they could face by investing in bitcoin — market risks, accounting and earnings risks, possibly regulatory risks. And even if the risks don't seem to be out front for the moment, it's rarely a good idea to put too many of your eggs in one basket.
© Francine McKenna, The Digging Company LLC, 2020
4 Comment2 ShareShare
Simple CPA
and the CEO is a bad character. KPMG lowered the bar on client acceptance. Always bites hard.
Expand full comment
remember who audited FNMA (trillion company with complex derivatives) for $2million a year? KPMG. This is scary
TopNewCommunityWhat is The Dig?AboutAbout

redpajama_set_name: RedPajamaCommonCrawl


text:
NGC 4541 ist eine Balken-Spiralgalaxie vom Hubble-Typ SBbc im Sternbild Jungfrau auf der Ekliptik. Sie ist schätzungsweise 304 Millionen Lichtjahre von der Milchstraße entfernt und hat einen Durchmesser von etwa 145.000 Lichtjahren.
Im selben Himmelsareal befindet sich u. a. die Galaxie NGC 4437.

Die Supernova SN 2007gq wurde hier beobachtet.

Das Objekt wurde am 1. Januar 1786 von dem deutsch-britischen Astronomen Wilhelm Herschel entdeckt.

Weblinks
 SIMBAD Astronomical Database

Einzelnachweise

Balkenspiralgalaxie

redpajama_set_name: RedPajamaWikipedia


Chitra Pournami is a Hindu festival observed on the full moon day in the month of Chithirai or Chaitra, which corresponds to the months of April–May in the English calendar. It is celebrated to mark the birth anniversary of Chitragupta, the assistant of the God of death, Yama. The word Chitra means 'picture' and Gupta means 'hidden' which symbolizes Chitragupta's role as the keeper of records of all the actions and deeds committed by a person on Earth. Thus, Chitragupta is popularly called as the bookkeeper of heaven who will ultimately decide whether a person goes to heaven or to hell. Astrologically speaking, Chitragupta is the overlord of the shadow planet 'Ketu' and worshiping him on Chitra Pournami day will overcome 'Ketu Dosha' in the horoscope. Chitragupta is a popular deity in the Southern regions of the country, but there are very few temples dedicated to him. There is a prominent shrine for Chitragupta in Kanchipuram in the state of Tamilnadu. Devotees have a bath in holy rivers or other water bodies to wash away their sins and special poojas are conducted in honor of the deity on the Chitra Pournami day. Observing a fast and feeding the poor are also some of the rituals observed on Chitra Pournami day.
Many people celebrate Chitra Pournami in a grand manner at home. On the night before Chitra Pournami, Pooja lamps are washed, and turmeric, kum kum dots (vermillion) and thread are kept ready for performing Pooja on the next day. The house is also thoroughly swept and kept clean. Neem flowers, dried flowers, a coconut, a raw mango and a palm hand fan are also kept for the Pooja.
They then proceed to decorate the home with colorful Maakolams (rice flour drawing) and start making preparations for the Pooja. Usually, a thearkolam (rice flour drawing of chariot) is drawn in the entrance of the house and the Pooja room. The foot of Chitragupta along with an umbrella, hand fan, stick, foot of a bull, foot of a horse and flag is drawn, to welcome Chitragupta into the house. On the day of Chitra Pournami, people wake up early and have head bath, and then go on to prepare the dishes for Naivedyam. Sweet pidikozhukattai, Panagam, vellaipongal, mango pachadi and neermor are some of the other dishes prepared for the puja. If possible, all the Naivedyam dishes should be kept and served in mud pots and plates. The Pooja celebrations should start at an auspicious time of the day, and Rahu Kalam or Yama Kandam times should be avoided. At the appropriate time, a lamp is lit and the Naivedyam offerings are placed before the deity. The muram (winnowing basket) with Navadhaniyam (blend of nine grains), hand written paper and pen, betel leaves, nuts, bananas and a coconut are kept ready for the Pooja. The panakam and neermor are kept in bowls while the sweet pidikozhukattai and white pongal are placed in a plate. In keeping with Hindu tradition, the Pooja lamp and dhoop sticks are waved before the deity while an Aarti is performed.
Many people recite stories of Chitragupta and chant some holy Slokas while performing the Pooja. Finally, after concluding all the rituals and successfully completing the Pooja, prasadam is distributed among all those present. People then go on to enjoy a good lunch specially prepared for the occasion of Chitra Pournami. Vada and payasam are some of the favorite items served on the day, along with other dishes. Though the general procedure remains the same, there could be slight variations in the way things are carried out in the Pooja. Many people offer food to the poor and needy to get the blessings of the almighty and absolve the sins committed in their sojourn in the world. All said and done, Chitra Pournami infuses faith, devotion and hope to lead a meaningful life, and gives us the courage to transit into a higher plane of existence when the time comes.


text:
$2 million collection of Supreme T-shirts goes on sale at Christie's
By David Matthews
The world's most complete collection of Supreme brand T-shirts is expected to fetch $2 million in a private sale at Christie's.
According to CNBC, the collection includes 253 T-shirts, more than $7,900 per shirt, dating back to when the brand launched in 1994 in a Manhattan skateboard shop.
The collection is currently owned by 21-year-old Canadian fashion student James Bogart who is excited about the potential windfall from the sale but will miss the process of tracking down the shirts.
"I think it'll be a little bit bittersweet," he told CNBC. "For me, it was always about the hunt. And the fact that so many people deem to this collection impossible to be completed. So once it was completed, there was a sense of great relief and great pride, but I really did want to put it on a stage where it could be appreciated and do the collection justice."
The sale is part of Christie's first ever Supreme auction which includes a Supreme/Louis Vuitton skateboard, a set of Supreme/ The North Face jackets and backpacks, a Supreme/Honda dirt bike, a Supreme pinball machine and more.


Michael Noonan will be our key figure in Europe during the Irish EU presidency beginning in January and his views about this and about Europe take on a special significance. The looming inevitability of this awesome eventuality in the present circumstances has worried many within the public service, not least those who consider we are not up to the job.
We are failing to grapple properly with a multitude of domestic problems, and to have the burden of a central role in the supposed matter of running Europe casts a huge shadow over our competence. No matter; the task is upon us now and we need desperately, I think, to accommodate ourselves within the reality that faces us, with our own unstable Budget side by side with the breakdown of the EU budget talks last week.
Mr Noonan's views on the Government's objectives for the Irish presidency may be briefly summarised. He sees a political union for Europe, involving a more centralised EU, as inevitable. Well he might, since he and the two parties in power, together with Fianna Fail, have, with might and main, worked to deliver us into that political union well before the need for it has been established.
We are more governed from Europe, and psychologically more conditioned to being so governed, than any other state.
In what would appear to be a contradictory interpretation of the future, he sees difficulties in bringing the rest of the people along – in my view, Ireland is already there – with what he called last week "a deepening of integration". And he went on to identify "budgetary sovereignty" for us and the other 26 EU member states being limited by "integration" but still being there and still having "democratic legitimacy".
We are between the rock of budgetary constraint, imposed by the EU from outside and without democratic debate; and the hard place of not being able to control wages and pensions, raise additional direct taxes, or balance the books. Mr Noonan said "fiscal discipline is not the same as austerity". We have both, and he seems powerless to change this.
There seemed to be a further contradiction in his view that the necessary EU economic governance could be achieved by a "big bang'' approach, yet one that was agreed, not imposed. I admire Mr Noonan's physical and mental resources since he made this relatively optimistic speech on Friday, having almost literally crawled away exhausted from that EU meeting, claiming simply he was "'tired" and making no comment about how it had gone, nor what Ireland had got out of it, which was precisely nothing.
One of the things that was missing from this Friday speech was any reference to the outcome as it affects the UK and Ireland – a crucial issue confronting us and likely to impact on our future more than any other.
The position taken by David Cameron last week represented by far the biggest challenge to all the things Mr Noonan expressed himself favouring on the eve of the Irish presidency.
The British prime minister, together with the German, Dutch and Swedish leaders, were collectively responsible for blocking the EU budget deal, an exercise in precisely the democratic intervention of four powerful net contributors whose delivery of their version of this was directly parallel with what Mr Noonan praised (in the abstract, it must be said) in his speech on Friday.
Mr Cameron was not an isolated figure when he walked away from the summit, but a spokesperson for other democratic states expressing some disgust at what he described as the "insult" of Manuel Barroso refusing to cut even one euro from the extravagantly huge expenditure on running the EU bureaucracy.
The European Commission president needs to be told by Mr Noonan to come back in January with significant cuts in this area if change is to be achieved. One wonders if this exercise in democracy will materialise when we take over? Will Mr Noonan have such nerve?
Far more important for Mr Cameron, however, was the fact that he walked away from the collapsed EU budget summit as part of an inner team of crucial importance – those who pay the piper – and not isolated, as many anticipated he would be. He is in a position to face his own party at home having protected British interests, having delivered a much-needed rap over the knuckles to Mr Barroso, who has irritated many other EU leaders, and having strengthened the British position for a re-negotiation with the EU rather than a departure from it.
If Ireland still thinks at all of its vital interests, politically and in economic and trade terms, then what is happening in Britain is food for thought and, in the case of Mr Noonan, requires careful recognition of Britain's dilemma.
Mr Cameron judged things well last week. Most importantly, he avoided confrontation with the European Union while at the same time forming bonds with the more powerful grouping of net contributors. What was held in abeyance was the north-south problem and the marginal role into which the French president was pushed.
The relationship between ourselves and Britain should be based on trust and friendship.
This needs reference points. It is not widely enough debated, as the past few days have shown; and it involves another vital interest of ours – the future of Irish north-south relations in the event of the UK being forced into a withdrawal from the EU, either as a result of EU impatience or of Conservative intolerance.
This at-present unlikely option would impact on Scotland, on Northern Ireland and ourselves, on the United States and on our relationship with Europe and with Britain, both Scotland and Northern Ireland remaining important in their impact on us, though becoming far more complex and difficult.
The present Government pays little attention to all of this – no different from the previous governments under Brian Cowen and Bertie Ahern.


Precisely when the Silent Hill series started to go downhill seems to be associated roughly with the disbanding of the original development team, but the reasons newer teams have failed to create games as good as the earlier ones in the series is a much more difficult matter to discern. The intention of this article is to explore the features that made the early Silent Hill games such standouts in order to explain why the series went downhill with later games.
The important point here is that this type of horror exploits or taps into common or universal fears shared by players. The problem is that newer releases of the games have really failed on this specific point.
Take Silent Hill, the first game in the series, as an example. The game very effectively exploited a collection of fears and phobias that are commonly shared by people. Insects featured prominently from cockroaches to a giant moth because humans have a common uneasiness around such things. Silent Hill simply magnified this by making them larger and more aggressive, but still clearly insects. Silent Hill 2 used more abstract horrors, but focused on more emotional adult fears associated with sexuality and murder. Silent Hill 3 focused on fears associated with pregnancy and the female reproductive cycle.
This problem is a little more subtle but still prevalent in newer releases of Silent Hill and is no doubt at least partially responsible for it having gone downhill. The core of the issue is that there is a lacking of the concept of 'Ma', which is the Japanese concept of negative space. In essence, the silence between claps when you clap your hands. The problem with lacking this kind of stillness is that the player does not have time to think and reflect on what they have seen or expect to see, which is a big part of the build up when it comes to horror. Even the jump-scare variety of horror that is somewhat tedious requires it. Shattered Memories and to a lesser extent Downpour did seem to have a little more stillness than the full-volume Homecoming, but none of them really had a great sense of timing between plot elements.
Stop including Pyramid Head in everything. Please. Focus on making a good, original game rather than trying to commercialize a game with fan service. Perhaps it is simply time to stop making Silent Hill games.


text:
"The future of design is in the creation of tools": Meet the Space Type Generator
Jyni Ong
Space Type Generator is not only anyone's gateway into the mind-boggling world of motion type design, it is also an extremely fun tool to play around with. For anyone that is a complete novice to motion graphics (myself included) simply opening this tool in your web browser makes you feel more technology-fluent, as what unfolds before our very eyes once that webpage loads, is a reservoir of hypnotically moving type.
Though we'd like to take credit for the bespoke creations that are possible due to the Space Type Generator, the handy work of the type motion design tool is really down to Kiel Danger (yes that is his middle name) Mutschelknaus. Beginning his career in advertising, Kiel went onto study an MFA in 2D design in Detroit which is where he first started experimenting with motion design. "At Cranbrook Academy of Arts I got really excited about learning new tools and technology," Kiel tells It's Nice That. After graduating, he became a full-time faculty member at the Maryland Institute College of Art's graphic design department; a profession he continues to this day which also proves "very helpful with these type explorations."
"Most of the content we consume is on a screen," explains Kiel on his interest in moving type. "Understanding the potential of that design in motion is a necessity. In the larger context of graphic design, motion and generative design are basically new. It's a history being written (or coded?) right now, and being part of that conversation is incredibly exciting and filled with the unknown."
The concept for the generator began around a year ago when Kiel designed a series of faux AR videos on Instagram in the form of a moving typographic chandelier made in After Effects. "Designing the pieces in After Effects was a good place to start," says Kiel on his type experiments, "but it was cumbersome, and as the forms became more complex, it became harder to iterate. By this point, I knew the geometry well and decided to create a version in the coding programme Processing. It translated perfectly."
From there, Kiel incorporated parameters on the fly as the type was moving. Gradually, he layered up different kinds of motion and added variables using sliders for more interaction. "It exploded from there," adds Kiel on his creation. With The Space Type Generator now live and online, there are still an "overwhelming" amount of tweaks Kiel hopes to add to the type tool. These include adding actual typefaces to the current format, including non-Latin alphabets for its international users. Not to mention a number of technological advancements that Kiel is in the process of implementing.
"I think the future (or a future) of design is in the creation of tools rather than the creation of the designs," says Kiel. "Space Type Generator is in this spirit, it creates a fluid system rather than a final form. I'd like the users to consider this notion, and think of this project as a new method of design in itself." As the generator is open-source and the code is on Github, Kiel welcomes any users to help iterate and design the collaborative tool further, so we can all enjoy the tool, whether it's for reasons relating to design or just plain fun.
In the 8-bit Baoverse app, it's okay to play with your food
Review of the Year 2022: Top 25 Features
It's Nice That and RoomFifty bring you a collection of prints from our favourite artists – just in time for Christmas!
Why the world needs more 3D designers
Average digital designer produces equivalent of one-way flight in emissions a year, report shows
www.spacetypegenerator.com
www.kielm.com
Jyni joined It's Nice That as an editorial assistant in August 2018 after graduating from The Glasgow School of Art's Communication Design degree. In March 2019 she became a staff writer and in June 2021, she was made associate editor.


text:
/*!
 * \file
 * \brief Vulkan Dynamic Rendering Random Tests
 *//*--------------------------------------------------------------------*/

#include "deRandom.hpp"

#include "tcuImageCompare.hpp"
#include "tcuTestLog.hpp"

#include "vkBarrierUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vktDrawBufferObjectUtil.hpp"
#include "vktDynamicRenderingRandomTests.hpp"
#include "vkImageUtil.hpp"
#include "vkObjUtil.hpp"
#include "vktTestCase.hpp"
#include "vkTypeUtil.hpp"

#include <iostream>

namespace vkt
{
namespace renderpass
{
namespace
{

using namespace vk;

using tcu::UVec2;
using tcu::Vec4;

const deUint32	maxQueries		= 50u * 3u; // multiview with 3 bits can be used
const deUint32	numLayers		= 4u;

struct TestParameters
{
	VkFormat	imageFormat;
	UVec2		renderSize;
	bool		enableGeometry;
	bool		enableTessellation;
	deUint32	randomSeed;
};

struct PushConstantData
{
	Vec4	scale;
	Vec4	offset;
	Vec4	color;
	deInt32	layer;
};

class DynamicRenderingTestInstance : public TestInstance
{
public:
								DynamicRenderingTestInstance	(Context&				context,
																 const TestParameters&	parameters);
protected:
	virtual tcu::TestStatus		iterate							(void);

	TestParameters				m_parameters;
	Move<VkImage>				m_imageColor;
	Move<VkImageView>			m_colorAttachmentView;
	de::MovePtr<Allocation>		m_imageColorAlloc;
	de::SharedPtr<Draw::Buffer>	m_imageBuffer;
	deUint32					m_layerSizeBytes;
	Move<VkShaderModule>		m_vertexModule;
	Move<VkShaderModule>		m_vertexPassthroughModule;
	Move<VkShaderModule>		m_vertexLayerModule;
	Move<VkShaderModule>		m_geometryModule;
	Move<VkShaderModule>		m_geometryLayerModule;
	Move<VkShaderModule>		m_tscModule;
	Move<VkShaderModule>		m_tseModule;
	Move<VkShaderModule>		m_fragmentModule;
	de::SharedPtr<Draw::Buffer>	m_vertexBuffer;
	Move<VkPipelineLayout>		m_pipelineLayout;
	de::SharedPtr<Draw::Buffer>	m_queryResults;
	Move<VkQueryPool>			m_queryPool;
	Move<VkCommandPool>			m_cmdPool;
	de::Random					m_random;
	Move<VkPipeline>			m_pipelineBasic;
	Move<VkPipeline>			m_pipelineGeom;
	Move<VkPipeline>			m_pipelineTess;
	Move<VkPipeline>			m_pipelineLayer;
	Move<VkPipeline>			m_pipelineMultiview;
};

DynamicRenderingTestInstance::DynamicRenderingTestInstance (Context&				context,
															const TestParameters&	parameters)
: TestInstance	(context)
, m_parameters	(parameters)
, m_random		(parameters.randomSeed)
{
	const DeviceInterface&		vk			= m_context.getDeviceInterface();
	const VkDevice				device		= m_context.getDevice();
	Allocator&					allocator	= m_context.getDefaultAllocator();

	m_cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex());

	// Vertices.
	{
		std::vector<Vec4>			vertices	=
		{
			Vec4(-0.5f,  0.5f, 0.0f, 1.0f),
			Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
			Vec4( 0.5f,  0.5f, 0.0f, 1.0f),
			Vec4( 0.5f, -0.5f, 0.0f, 1.0f)
		};

		const VkDeviceSize			bufferSize	= vertices.size() * sizeof(vertices[0]);
		const VkBufferCreateInfo	bufferInfo	= makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);

		m_vertexBuffer	= Draw::Buffer::createAndAlloc(vk, device, bufferInfo, allocator, MemoryRequirement::HostVisible);

		deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), vertices.data(), static_cast<std::size_t>(bufferSize));
		flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
	}

	// Create color image.
	{
		const VkImageUsageFlags			imageUsage			= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
															  VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
															  VK_IMAGE_USAGE_TRANSFER_DST_BIT;
		m_layerSizeBytes									= m_parameters.renderSize.x() *
															  m_parameters.renderSize.y() *
															  tcu::getPixelSize(mapVkFormat(m_parameters.imageFormat));
		const VkDeviceSize				imageBufferSize		= m_layerSizeBytes * numLayers;

		const VkImageCreateInfo			imageInfo			=
		{
			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType
			DE_NULL,										// const void*				pNext
			(VkImageCreateFlags)0,							// VkImageCreateFlags		flags
			VK_IMAGE_TYPE_2D,								// VkImageType				imageType
			m_parameters.imageFormat,						// VkFormat					format
			makeExtent3D(m_parameters.renderSize.x(),
						 m_parameters.renderSize.y(), 1),	// VkExtent3D				extent
			1u,												// deUint32					mipLevels
			numLayers,										// deUint32					arrayLayers
			VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples
			VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling
			imageUsage,										// VkImageUsageFlags		usage
			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode
			0u,												// deUint32					queueFamilyIndexCount
			DE_NULL,										// const deUint32*			pQueueFamilyIndices
			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout
		};

		const VkBufferCreateInfo		bufferInfo			= makeBufferCreateInfo(imageBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);

		m_imageColor		= makeImage(vk, device, imageInfo);
		m_imageColorAlloc	= bindImage(vk, device, allocator, *m_imageColor, MemoryRequirement::Any);
		m_imageBuffer		= Draw::Buffer::createAndAlloc(vk, device, bufferInfo, allocator, MemoryRequirement::HostVisible);

		const VkImageSubresourceRange	imageSubresource	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers);

		m_colorAttachmentView	= makeImageView(vk, device, *m_imageColor, VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_parameters.imageFormat, imageSubresource);

		const Allocation				alloc				= m_imageBuffer->getBoundMemory();
		deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(imageBufferSize));
		flushAlloc(vk, device, alloc);
	}

	// Pipeline layout.
	{
		const auto	pcStages	= VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT;
		const auto	pcSize		= static_cast<uint32_t>(sizeof(PushConstantData));
		const auto	pcRange		= makePushConstantRange(pcStages, 0u, pcSize);

		m_pipelineLayout = makePipelineLayout(vk, device, 0u, DE_NULL, 1u, &pcRange);
	}

	// Shader modules.
	{
		m_vertexModule				= createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u);
		m_fragmentModule			= createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
		if (m_parameters.enableGeometry)
		{
			m_vertexPassthroughModule	= createShaderModule(vk, device, m_context.getBinaryCollection().get("vertPassthrough"), 0u);
			m_vertexLayerModule			= createShaderModule(vk, device, m_context.getBinaryCollection().get("vertLayer"), 0u);
			m_geometryModule			= createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
			m_geometryLayerModule		= createShaderModule(vk, device, m_context.getBinaryCollection().get("geomLayer"), 0u);
		}
		if (m_parameters.enableTessellation)
		{
			m_tscModule					= createShaderModule(vk, device, m_context.getBinaryCollection().get("tsc"), 0u);
			m_tseModule					= createShaderModule(vk, device, m_context.getBinaryCollection().get("tse"), 0u);
		}
	}

	// Pipelines.
	{
		const std::vector<vk::VkViewport>	viewports			(1u, vk::makeViewport(m_parameters.renderSize));
		const std::vector<vk::VkRect2D>		scissors			(1u, vk::makeRect2D(m_parameters.renderSize));

		VkPipelineRenderingCreateInfoKHR	renderingCreateInfo	=
		{
			VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,	// VkStructureType	sType
			DE_NULL,												// const void*		pNext
			0u,														// deUint32			viewMask
			1u,														// deUint32			colorAttachmentCount
			&m_parameters.imageFormat,								// const VkFormat*	pColorAttachmentFormats
			VK_FORMAT_UNDEFINED,									// VkFormat			depthAttachmentFormat
			VK_FORMAT_UNDEFINED,									// VkFormat			stencilAttachmentFormat
		};

		m_pipelineBasic		= makeGraphicsPipeline(vk,										// const DeviceInterface&							vk
												   device,									// const VkDevice									device
												   *m_pipelineLayout,						// const VkPipelineLayout							pipelineLayout
												   *m_vertexModule,							// const VkShaderModule								vertexShaderModule
												   DE_NULL,									// const VkShaderModule								tessellationControlShaderModule
												   DE_NULL,									// const VkShaderModule								tessellationEvalShaderModule
												   DE_NULL,									// const VkShaderModule								geometryShaderModule
												   *m_fragmentModule,						// const VkShaderModule								fragmentShaderModule
												   DE_NULL,									// const VkRenderPass								renderPass
												   viewports,								// const std::vector<VkViewport>&					viewports
												   scissors,								// const std::vector<VkRect2D>&						scissors
												   VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	// const VkPrimitiveTopology						topology
												   0u,										// const deUint32									subpass
												   0u,										// const deUint32									patchControlPoints
												   DE_NULL,									// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
												   DE_NULL,									// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
												   DE_NULL,									// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
												   DE_NULL,									// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
												   DE_NULL,									// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
												   DE_NULL,									// const VkPipelineDynamicStateCreateInfo*			dynamicStateCreateInfo
												   &renderingCreateInfo);					// const void*										pNext

		if (m_parameters.enableGeometry)
		{
			m_pipelineGeom = makeGraphicsPipeline(
					vk,									// const DeviceInterface&							vk
					device,								// const VkDevice									device
					*m_pipelineLayout,					// const VkPipelineLayout							pipelineLayout
					*m_vertexPassthroughModule,			// const VkShaderModule								vertexShaderModule
					DE_NULL,							// const VkShaderModule								tessellationControlShaderModule
					DE_NULL,							// const VkShaderModule								tessellationEvalShaderModule
					*m_geometryModule,					// const VkShaderModule								geometryShaderModule
					*m_fragmentModule,					// const VkShaderModule								fragmentShaderModule
					DE_NULL,							// const VkRenderPass								renderPass
					viewports,							// const std::vector<VkViewport>&					viewports
					scissors,							// const std::vector<VkRect2D>&						scissors
					VK_PRIMITIVE_TOPOLOGY_POINT_LIST,	// const VkPrimitiveTopology						topology
					0u,									// const deUint32									subpass
					0u,									// const deUint32									patchControlPoints
					DE_NULL,							// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
					DE_NULL,							// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
					DE_NULL,							// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
					DE_NULL,							// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
					DE_NULL,							// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
					DE_NULL,							// const VkPipelineDynamicStateCreateInfo*			dynamicStateCreateInfo
					&renderingCreateInfo);				// const void*										pNext

			m_pipelineLayer = makeGraphicsPipeline(
					vk,										// const DeviceInterface&							vk
					device,									// const VkDevice									device
					*m_pipelineLayout,						// const VkPipelineLayout							pipelineLayout
					*m_vertexLayerModule,					// const VkShaderModule								vertexShaderModule
					DE_NULL,								// const VkShaderModule								tessellationControlShaderModule
					DE_NULL,								// const VkShaderModule								tessellationEvalShaderModule
					*m_geometryLayerModule,					// const VkShaderModule								geometryShaderModule
					*m_fragmentModule,						// const VkShaderModule								fragmentShaderModule
					DE_NULL,								// const VkRenderPass								renderPass
					viewports,								// const std::vector<VkViewport>&					viewports
					scissors,								// const std::vector<VkRect2D>&						scissors
					VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	// const VkPrimitiveTopology						topology
					0u,										// const deUint32									subpass
					0u,										// const deUint32									patchControlPoints
					DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
					DE_NULL,								// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
					DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
					DE_NULL,								// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
					DE_NULL,								// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
					DE_NULL,								// const VkPipelineDynamicStateCreateInfo*			dynamicStateCreateInfo
					&renderingCreateInfo);					// const void*										pNext
		}

		if (m_parameters.enableTessellation)
		{
			m_pipelineTess = makeGraphicsPipeline(
					vk,										// const DeviceInterface&							vk
					device,									// const VkDevice									device
					*m_pipelineLayout,						// const VkPipelineLayout							pipelineLayout
					*m_vertexModule,						// const VkShaderModule								vertexShaderModule
					*m_tscModule,							// const VkShaderModule								tessellationControlShaderModule
					*m_tseModule,							// const VkShaderModule								tessellationEvalShaderModule
					DE_NULL,								// const VkShaderModule								geometryShaderModule
					*m_fragmentModule,						// const VkShaderModule								fragmentShaderModule
					DE_NULL,								// const VkRenderPass								renderPass
					viewports,								// const std::vector<VkViewport>&					viewports
					scissors,								// const std::vector<VkRect2D>&						scissors
					vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,	// const VkPrimitiveTopology						topology
					0u,										// const deUint32									subpass
					4u,										// const deUint32									patchControlPoints
					DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
					DE_NULL,								// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
					DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
					DE_NULL,								// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
					DE_NULL,								// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
					DE_NULL,								// const VkPipelineDynamicStateCreateInfo*			dynamicStateCreateInfo
					&renderingCreateInfo);					// const void*										pNext
		}

		renderingCreateInfo.viewMask = 0xb; // 1011b
		m_pipelineMultiview	= makeGraphicsPipeline(vk,										// const DeviceInterface&							vk
												   device,									// const VkDevice									device
												   *m_pipelineLayout,						// const VkPipelineLayout							pipelineLayout
												   *m_vertexModule,							// const VkShaderModule								vertexShaderModule
												   DE_NULL,									// const VkShaderModule								tessellationControlShaderModule
												   DE_NULL,									// const VkShaderModule								tessellationEvalShaderModule
												   DE_NULL,									// const VkShaderModule								geometryShaderModule
												   *m_fragmentModule,						// const VkShaderModule								fragmentShaderModule
												   DE_NULL,									// const VkRenderPass								renderPass
												   viewports,								// const std::vector<VkViewport>&					viewports
												   scissors,								// const std::vector<VkRect2D>&						scissors
												   VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	// const VkPrimitiveTopology						topology
												   0u,										// const deUint32									subpass
												   0u,										// const deUint32									patchControlPoints
												   DE_NULL,									// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
												   DE_NULL,									// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
												   DE_NULL,									// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
												   DE_NULL,									// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
												   DE_NULL,									// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
												   DE_NULL,									// const VkPipelineDynamicStateCreateInfo*			dynamicStateCreateInfo
												   &renderingCreateInfo);					// const void*										pNext
	}

	// Query result buffer.
	{
		const VkDeviceSize			bufferSize = 1024u;
		const VkBufferCreateInfo	bufferInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);

		m_queryResults = Draw::Buffer::createAndAlloc(vk, device, bufferInfo, allocator, MemoryRequirement::HostVisible);
	}

	// Query pool.
	{
		VkQueryPoolCreateInfo	queryPoolInfo	=
		{
			VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	// VkStructureType					sType
			DE_NULL,									// const void*						pNext
			0,											// VkQueryPoolCreateFlags			flags
			vk::VK_QUERY_TYPE_OCCLUSION,				// VkQueryType						queryType
			maxQueries,									// uint32_t							queryCount
			0											// VkQueryPipelineStatisticFlags	pipelineStatistics
		};

		m_queryPool	= createQueryPool(vk, device, &queryPoolInfo);
	}
}

tcu::TestStatus DynamicRenderingTestInstance::iterate (void)
{
	const DeviceInterface&				vk				= m_context.getDeviceInterface();
	const VkDevice						device			= m_context.getDevice();
	const VkQueue						queue			= m_context.getUniversalQueue();
	const deUint32						queueFamily		= m_context.getUniversalQueueFamilyIndex();
	tcu::TestLog&						log				= m_context.getTestContext().getLog();

	std::vector<Move<VkCommandBuffer>>	cmdBuffers;
	std::vector<Move<VkCommandBuffer>>	secondaryCmdBuffers;
	std::vector<tcu::TextureLevel>		ref;

	for (deUint32 i = 0; i < numLayers; i++)
	{
		ref.emplace_back(mapVkFormat(m_parameters.imageFormat), m_parameters.renderSize.x(), m_parameters.renderSize.y(), 1u);

		tcu::PixelBufferAccess	access = ref[i].getAccess();

		for (deUint32 y = 0; y < m_parameters.renderSize.x(); y++)
			for (deUint32 x = 0; x < m_parameters.renderSize.x(); x++)
				access.setPixel(Vec4(0.0f), x, y);
	}

	cmdBuffers.push_back(allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
	beginCommandBuffer(vk, *cmdBuffers.back());
	vk.cmdResetQueryPool(*cmdBuffers.back(), *m_queryPool, 0, maxQueries);

	clearColorImage(vk, device, queue, queueFamily, *m_imageColor, Vec4(0.0),
					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
					VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, numLayers);

	VkRenderingFlagsKHR					prevFlags		= 0;
	Vec4								clearColor		= Vec4(0.0f);
	VkRect2D							renderArea		= makeRect2D(0, 0, 0, 0);
	VkAttachmentLoadOp					loadOp			= VK_ATTACHMENT_LOAD_OP_CLEAR;
	deUint32							renderWidth		= 0u;
	deUint32							renderHeight	= 0u;
	deUint32							renderX			= 0u;
	deUint32							renderY			= 0u;
	deUint32							quadShrink		= 0u;
	deUint32							queryIndex		= 0u;
	std::vector<uint32_t>				queryMultiviewCount;

	enum PipelineType
	{
		PIPELINE_TYPE_VERTEX_FRAGMENT = 0,
		PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT = 1,
		PIPELINE_TYPE_VERTEX_TESS_FRAGMENT = 2,
		PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER = 3,
		PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW = 4,
		PIPELINE_TYPE_ATTACHMENT_CLEAR = 5,
		PIPELINE_TYPE_MAX = 6
	} pipelineType = PIPELINE_TYPE_VERTEX_FRAGMENT;

	std::vector<VkPipeline>				pipelines		= {*m_pipelineBasic, *m_pipelineGeom, *m_pipelineTess, *m_pipelineLayer, *m_pipelineMultiview, *m_pipelineBasic};

	deUint32							validPipelines	= (1 << PIPELINE_TYPE_VERTEX_FRAGMENT) | (1 << PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW) | (1 << PIPELINE_TYPE_ATTACHMENT_CLEAR);

	if (m_parameters.enableGeometry)
		validPipelines |= (1 << PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT) | (1 << PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER);

	if (m_parameters.enableTessellation)
		validPipelines |= (1 << PIPELINE_TYPE_VERTEX_TESS_FRAGMENT);

	const int							numIterations	= 50;

	for (int i = 0; i < numIterations; i++)
	{
		VkRenderingFlagsKHR		flags								= 0;
		bool					useSecondaryCmdBuffer				= m_random.getUint32() % 5 == 0;
		bool					bindPipelineBeforeBeginRendering	= m_random.getBool();

		if (useSecondaryCmdBuffer)
		{
			flags |= VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR;
			// Pipeline bind needs to go to the same command buffer that has the draw call.
			bindPipelineBeforeBeginRendering = false;
		}

		if (prevFlags & VK_RENDERING_SUSPENDING_BIT_KHR)
		{
			// Resuming: Don't touch the beginRendering parameters as they need to
			// match with the previous command buffer.

			flags |= VK_RENDERING_RESUMING_BIT_KHR;

			// Use a new command buffer.
			VK_CHECK(vk.endCommandBuffer(*cmdBuffers.back()));

			cmdBuffers.push_back(allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
			beginCommandBuffer(vk, *cmdBuffers.back());

			// Make the drawn quad smaller so the previous quad is still visible.
			quadShrink++;

			// Pipeline bind is not allowed between suspend and resume.
			bindPipelineBeforeBeginRendering = false;
		}
		else
		{
			// Not resuming: we can randomize new beginRendering parameters.
			clearColor		= Vec4(m_random.getFloat(), m_random.getFloat(), m_random.getFloat(), 1.0f);

			const deUint32 minAreaSize = 32u;
			// Use a render area with an even size to make the margin around the quad symmetrical.
			renderWidth		= (m_random.getUint32() % (m_parameters.renderSize.x() / 2 - minAreaSize) + minAreaSize) & (~1u);
			renderHeight	= (m_random.getUint32() % (m_parameters.renderSize.y() / 2 - minAreaSize) + minAreaSize) & (~1u);
			renderX			= m_random.getUint32() % (m_parameters.renderSize.x() - renderWidth);
			renderY			= m_random.getUint32() % (m_parameters.renderSize.y() - renderHeight);
			renderArea		= { makeOffset2D(renderX, renderY), makeExtent2D(renderWidth, renderHeight) };
			loadOp			= m_random.getBool() ? vk::VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
			quadShrink		= 0u;
		}

		// Randomize pipeline type on every round. Multiview pipeline is an exception: the view mask cannot change
		// between suspend and resume.
		if (!(prevFlags & VK_RENDERING_SUSPENDING_BIT_KHR) || pipelineType != PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW)
		{
			deUint32 pipelineMask = validPipelines;

			if (prevFlags & VK_RENDERING_SUSPENDING_BIT_KHR)
			{
				// If resuming from non-multiview pipeline the new pipeline must also be non-multiview to keep the view mask.
				if (pipelineType != PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW)
					pipelineMask &= ~(1 << PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW);

				// The number of layers need to match too.
				const deUint32	layeredPipelines = (1 << PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER) | (1 << PIPELINE_TYPE_ATTACHMENT_CLEAR);
				if ((1 << pipelineType) & layeredPipelines)
				{
					// Filter out all non-layered pipelines.
					pipelineMask &= layeredPipelines;
				}
				else
				{
					// Filter out all layered pipelines.
					pipelineMask &= ~layeredPipelines;
				}
			}

			do
			{
				pipelineType = static_cast<PipelineType>(m_random.getUint32() % PIPELINE_TYPE_MAX);
			} while (((1 << pipelineType) & pipelineMask) == 0);
		}

		const bool				occlusionQuery						= m_random.getBool() && pipelineType != PIPELINE_TYPE_ATTACHMENT_CLEAR;
		const deUint32			viewMask							= pipelineType == PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW ? 0xb /* 1011b */ : 0;
		const bool				useLayers							= pipelineType == PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER || pipelineType == PIPELINE_TYPE_ATTACHMENT_CLEAR;
		const bool				suspend								= m_random.getUint32() % 5 == 0 && i != numIterations - 1;

		if (suspend)
		{
			flags |= VK_RENDERING_SUSPENDING_BIT_KHR;
		}

		const VkClearValue	clearValue								= makeClearValueColor(clearColor);

		if (bindPipelineBeforeBeginRendering)
			vk.cmdBindPipeline(*cmdBuffers.back(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[pipelineType]);

		// Begin rendering
		{
			const VkRenderingAttachmentInfoKHR	renderingAttachmentInfo	=
			{
				VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,	// VkStructureType			sType
				DE_NULL,											// const void*				pNext
				*m_colorAttachmentView,								// VkImageView				imageView
				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout			imageLayout
				VK_RESOLVE_MODE_NONE,								// VkResolveModeFlagBits	resolveMode
				DE_NULL,											// VkImageView				resolveImageView
				VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			resolveImageLayout
				loadOp,												// VkAttachmentLoadOp		loadOp
				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp		storeOp
				clearValue											// VkClearValue				clearValue
			};

			const VkRenderingInfoKHR			renderingInfo			=
			{
				VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,				// VkStructureType						sType
				DE_NULL,											// const void*							pNext
				flags,												// VkRenderingFlagsKHR					flags
				renderArea,											// VkRect2D								renderArea
				useLayers ? numLayers : 1u,							// deUint32								layerCount
				viewMask,											// deUint32								viewMask
				1u,													// deUint32								colorAttachmentCount
				&renderingAttachmentInfo,							// const VkRenderingAttachmentInfoKHR*	pColorAttachments
				DE_NULL,											// const VkRenderingAttachmentInfoKHR*	pDepthAttachment
				DE_NULL												// const VkRenderingAttachmentInfoKHR*	pStencilAttachment
			};

			vk.cmdBeginRendering(*cmdBuffers.back(), &renderingInfo);
		}

		if (useSecondaryCmdBuffer)
		{
			secondaryCmdBuffers.push_back(allocateCommandBuffer(vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));

			const VkCommandBufferInheritanceRenderingInfoKHR	inheritanceRenderingInfo	=
			{
					VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,	// VkStructureType			sType
					DE_NULL,															// const void*				pNext
					flags & ~VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR,	// VkRenderingFlagsKHR		flags
					viewMask,															// uint32_t					viewMask
					1u,																	// uint32_t					colorAttachmentCount
					&m_parameters.imageFormat,											// const VkFormat*			pColorAttachmentFormats
					VK_FORMAT_UNDEFINED,												// VkFormat					depthAttachmentFormat
					VK_FORMAT_UNDEFINED,												// VkFormat					stencilAttachmentFormat
					VK_SAMPLE_COUNT_1_BIT,												// VkSampleCountFlagBits	rasterizationSamples
			};

			const VkCommandBufferInheritanceInfo				bufferInheritanceInfo		=
			{
					vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,				// VkStructureType					sType
					&inheritanceRenderingInfo,											// const void*						pNext
					DE_NULL,															// VkRenderPass						renderPass
					0u,																	// deUint32							subpass
					DE_NULL,															// VkFramebuffer					framebuffer
					VK_FALSE,															// VkBool32							occlusionQueryEnable
					(VkQueryControlFlags)0u,											// VkQueryControlFlags				queryFlags
					(VkQueryPipelineStatisticFlags)0u									// VkQueryPipelineStatisticFlags	pipelineStatistics
			};

			const VkCommandBufferBeginInfo						commandBufBeginParams		=
			{
					VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,						// VkStructureType				sType
					DE_NULL,															// const void*					pNext
					VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT |
					VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,					// VkCommandBufferUsageFlags	flags
					&bufferInheritanceInfo
			};

			VK_CHECK(vk.beginCommandBuffer(*secondaryCmdBuffers.back(), &commandBufBeginParams));
		}

		const VkCommandBuffer&	cmdBuffer							= useSecondaryCmdBuffer ? *secondaryCmdBuffers.back() : *cmdBuffers.back();

		if (!bindPipelineBeforeBeginRendering)
			vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[pipelineType]);

		// Calculate push constant data.
		const float				scaleX								= static_cast<float>(renderArea.extent.width - quadShrink * 4) / static_cast<float>(m_parameters.renderSize.x());
		const float				scaleY								= static_cast<float>(renderArea.extent.height - quadShrink * 4) / static_cast<float>(m_parameters.renderSize.y());

		DE_ASSERT(scaleX > 0.0f);
		DE_ASSERT(scaleY > 0.0f);

		const float				pixelSizeX							= 2.0f / static_cast<float>(m_parameters.renderSize.x());
		const float				pixelSizeY							= 2.0f / static_cast<float>(m_parameters.renderSize.y());
		const Vec4				scale								= {scaleX + pixelSizeX * 0.5f, scaleY + pixelSizeY * 0.5f, 1.0f, 1.0f};
		const float				offsetX								= static_cast<float>(renderArea.offset.x - static_cast<int>(m_parameters.renderSize.x() - renderArea.extent.width) / 2) * pixelSizeX;
		const float				offsetY								= static_cast<float>(renderArea.offset.y - static_cast<int>(m_parameters.renderSize.y() - renderArea.extent.height) / 2) * pixelSizeY;
		const Vec4				offset								= {offsetX, offsetY, 0.0f, 0.0f};
		const deUint32			quadMarginX							= renderWidth / 4 + quadShrink;
		const deUint32			quadMarginY							= renderHeight / 4 + quadShrink;
		const deUint32			quadTop								= renderY + quadMarginY;
		const deUint32			quadBottom							= renderY + renderHeight - quadMarginY;
		const deUint32			quadLeft							= renderX + quadMarginX;
		const deUint32			quadRight							= renderX + renderWidth - quadMarginX;

		const Vec4				color								= {m_random.getFloat(), m_random.getFloat(), m_random.getFloat(), 1.0f};
		const deInt32			layer								= useLayers ? m_random.getUint32() % numLayers : 0;

		PushConstantData		pcd									= {scale, offset, color, layer};

		// Bind vertex buffer.
		{
			const VkBuffer		vertexBuffer		= m_vertexBuffer->object();
			const VkDeviceSize	vertexBufferOffset	= 0ull;

			vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
		}

		if (occlusionQuery)
			vk.cmdBeginQuery(cmdBuffer, *m_queryPool, queryIndex, 0);

		vk.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, 0, sizeof(pcd), &pcd);

		// Draw or clear a quad inside the render area.
		switch (pipelineType)
		{
			case PIPELINE_TYPE_VERTEX_FRAGMENT: // A quad using triangle strip.
			case PIPELINE_TYPE_VERTEX_TESS_FRAGMENT: // A quad using a tessellated patch.
			case PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER: // A quad using triangle strip drawn to a chosen layer.
			case PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW: // A quad using triangle strip drawn to layers 0, 1, and 3.
			{
				vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
			}
			break;
			case PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT: // A single point turned into a quad by geometry shader.
			{
				vk.cmdDraw(cmdBuffer, 1u, 1u, 0u, 0u);
			}
			break;
			case PIPELINE_TYPE_ATTACHMENT_CLEAR: // A quad using vkCmdClearAttachments
			{
				VkClearAttachment	clearAttachment	= { VK_IMAGE_ASPECT_COLOR_BIT, 0u, makeClearValueColor(color) };
				VkClearRect			rect			= { makeRect2D(quadLeft, quadTop, quadRight - quadLeft, quadBottom - quadTop), static_cast<deUint32>(layer), 1u };

				vk.cmdClearAttachments(cmdBuffer, 1u, &clearAttachment, 1u, &rect);
			}
			break;
			default:
			{
				DE_ASSERT(0 && "Unexpected pipeline type.");
			}
			break;
		}

		if (occlusionQuery)
		{
			vk.cmdEndQuery(cmdBuffer, *m_queryPool, queryIndex);
			if (pipelineType == PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW) {
				queryIndex += 3;
				queryMultiviewCount.push_back(3);
				queryMultiviewCount.push_back(0);
				queryMultiviewCount.push_back(0);
			}
			else
			{
				queryIndex++;
				queryMultiviewCount.push_back(1);
			}
		}

		deUint32				activeLayersClear					= 0x1;
		deUint32				activeLayersQuad					= 0x1;

		if (useLayers)
		{
			activeLayersClear	= (1 << numLayers) - 1;
			activeLayersQuad	= 1 << layer;
		}
		else if (pipelineType == PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW)
		{
			activeLayersClear = activeLayersQuad = viewMask;
		}

		// Update reference image.
		for (deUint32 l = 0; l < numLayers; l++)
		{
			tcu::PixelBufferAccess access = ref[l].getAccess();
			for (deUint32 y = renderY; y < renderY + renderHeight; y++)
				for (deUint32 x = renderX; x < renderX + renderWidth; x++)
				{
					if (loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR && !(flags & VK_RENDERING_RESUMING_BIT_KHR) && (activeLayersClear & (1 <<l)))
					{
						access.setPixel(clearColor, x, y);
					}

					if (x >= quadLeft && x < quadRight && y >= quadTop && y < quadBottom && (activeLayersQuad & (1 << l)))
					{
						// Inside the drawn quad.
						Vec4 refColor = color;

						if (pipelineType == PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW)
							refColor.z() = 0.15f * static_cast<float>(l);
						else if (pipelineType != PIPELINE_TYPE_ATTACHMENT_CLEAR)
							refColor.z() = 0.0f;

						access.setPixel(refColor, x, y);
					}
				}
		}

		if (useSecondaryCmdBuffer)
		{
			// End the secondary buffer
			VK_CHECK(vk.endCommandBuffer(cmdBuffer));

			// Call the secondary buffer
			vk.cmdExecuteCommands(*cmdBuffers.back(), 1u, &cmdBuffer);
		}

		vk.cmdEndRendering(*cmdBuffers.back());

		// Insert a pipeline barrier if not suspending.
		if (!suspend)
		{
			VkMemoryBarrier	barrier	=
			{
					VK_STRUCTURE_TYPE_MEMORY_BARRIER,		// VkStructureType	sType
					DE_NULL,								// const void*		pNext
					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,	// VkAccessFlags	srcAccessMask
					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT	// VkAccessFlags	dstAccessMask
			};

			vk.cmdPipelineBarrier(*cmdBuffers.back(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
								  1u, &barrier, 0u, DE_NULL, 0u, DE_NULL);
		}

		prevFlags = flags;
	}

	vk.cmdCopyQueryPoolResults(*cmdBuffers.back(), *m_queryPool, 0, queryIndex, m_queryResults->object(), 0, sizeof(deUint32), VK_QUERY_RESULT_WAIT_BIT);
	copyImageToBuffer(vk, *cmdBuffers.back(), *m_imageColor, m_imageBuffer->object(),
					  tcu::IVec2(m_parameters.renderSize.x(), m_parameters.renderSize.y()),
					  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, numLayers,
					  VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT);

	VK_CHECK(vk.endCommandBuffer(*cmdBuffers.back()));

	// Submit commands and wait.
	{
		const Unique<VkFence>			fence				(createFence(vk, device));
		std::vector<VkCommandBuffer>	cmdBufferHandles;

		for (const auto& cmdBuffer : cmdBuffers)
			cmdBufferHandles.push_back(*cmdBuffer);

		const VkSubmitInfo				submitInfo			=
		{
			VK_STRUCTURE_TYPE_SUBMIT_INFO,					// VkStructureType				sType
			DE_NULL,										// const void*					pNext
			0u,												// deUint32						waitSemaphoreCount
			DE_NULL,										// const VkSemaphore*			pWaitSemaphores
			DE_NULL,										// const VkPipelineStageFlags*	pWaitDstStageMask
			static_cast<deUint32>(cmdBufferHandles.size()),	// deUint32						commandBufferCount
			cmdBufferHandles.data(),						// const VkCommandBuffer*		pCommandBuffers
			0u,												// deUint32						signalSemaphoreCount
			DE_NULL,										// const VkSemaphore*			pSignalSemaphores
		};

		VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
		VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
	}

	// Verify result image.
	for (deUint32 i = 0; i < numLayers; i++)
	{
		const Allocation					allocColor			= m_imageBuffer->getBoundMemory();
		invalidateAlloc(vk, device, allocColor);

		const tcu::ConstPixelBufferAccess	resultColorImage	(mapVkFormat(m_parameters.imageFormat), m_parameters.renderSize.x(),
																 m_parameters.renderSize.y(), 1u, static_cast<deUint8*>(allocColor.getHostPtr()) + m_layerSizeBytes * i);

		if (!tcu::floatThresholdCompare(log, "Compare Color Image", "Result comparison", ref[i].getAccess(), resultColorImage, Vec4(0.02f), tcu::COMPARE_LOG_ON_ERROR))
		{
			return tcu::TestStatus::fail("Rendered color image is not correct");
		}
	}

	// Verify query pool results.
	{
		deUint32* queryPtr = static_cast<deUint32*>(m_queryResults->getBoundMemory().getHostPtr());
		invalidateAlloc(vk, device, m_queryResults->getBoundMemory());

		deUint32 i = 0;
		while (i < queryIndex)
		{
			uint32_t querySum = 0;
			for (uint32_t j = 0; j < queryMultiviewCount[i]; j++) {
				querySum += queryPtr[i];
			}
			if (querySum == 0)
			{
				return tcu::TestStatus::fail("Expected nonzero occlusion query results.");
			}
			i += queryMultiviewCount[i];
		}
	}

	return tcu::TestStatus::pass("Pass");
}

class RandomTestCase : public TestCase
{
public:
							RandomTestCase	(tcu::TestContext&		context,
											 const std::string&		name,
											 const std::string&		description,
											 const TestParameters&	parameters);
	virtual					~RandomTestCase	(void);

protected:
	virtual void			checkSupport	(Context&				context) const;
	virtual void			initPrograms	(SourceCollections&		programCollection) const;
	virtual TestInstance*	createInstance	(Context&				context) const;

	const TestParameters	m_parameters;
};

RandomTestCase::RandomTestCase (tcu::TestContext&		context,
								const std::string&		name,
								const std::string&		description,
								const TestParameters&	parameters)
: TestCase		(context, name, description)
, m_parameters	(parameters)
{
}

RandomTestCase::~RandomTestCase ()
{
}

void RandomTestCase::checkSupport (Context& context) const
{
	if (!context.requireDeviceFunctionality("VK_KHR_dynamic_rendering"))
		TCU_THROW(NotSupportedError, "VK_KHR_dynamic_rendering is not supported");

	const VkPhysicalDeviceDynamicRenderingFeaturesKHR& dynamicRenderingFeatures(context.getDynamicRenderingFeatures());

	if (dynamicRenderingFeatures.dynamicRendering == DE_FALSE)
		TCU_THROW(NotSupportedError, "dynamicRendering feature is not supported");

	if (m_parameters.enableGeometry)
		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
	if (m_parameters.enableTessellation)
		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
}

void RandomTestCase::initPrograms (SourceCollections& programCollection) const
{
	const std::string pushConstant =
		"layout( push_constant ) uniform constants\n"
		"{\n"
		"	vec4 scale;\n"
		"	vec4 offset;\n"
		"	vec4 color;\n"
		"	int layer;\n"
		"} pc;\n";

	// Vertex
	{
		std::ostringstream src;
		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
			<< "\n"
			<< "layout(location = 0) in vec4 position;\n"
			<< "layout(location = 0) out vec4 vsColor;\n"
			<< "\n"
			<< pushConstant
			<< "\n"
			<< "void main (void)\n"
			<< "{\n"
			<< "    gl_Position = position * pc.scale + pc.offset;\n"
			<< "    vsColor     = pc.color;\n"
			<< "}\n";
		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
	}

	// Passthrough vertex
    if (m_parameters.enableGeometry)
	{
		std::ostringstream src;
		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
			<< "\n"
			<< "layout(location = 0) in vec4 position;\n"
			<< "\n"
			<< "void main (void)\n"
			<< "{\n"
			<< "    gl_Position = position;\n"
			<< "}\n";
		programCollection.glslSources.add("vertPassthrough") << glu::VertexSource(src.str());
	}

	// Vertex layered
	if (m_parameters.enableGeometry)
	{
		std::ostringstream src;
		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
			<< "layout(location = 0) in vec4 position;\n"
			<< "layout(location = 0) out vec4 positionOut;\n"
			<< "\n"
			<< pushConstant
			<< "\n"
			<< "void main (void)\n"
			<< "{\n"
			<< "    positionOut = position * pc.scale + pc.offset;\n"
			<< "}\n";
		programCollection.glslSources.add("vertLayer") << glu::VertexSource(src.str());
	}

	// Geometry
	if (m_parameters.enableGeometry)
	{
		std::ostringstream src;
		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
			<< "\n"
			<< "layout(points) in;\n"
			<< "layout(triangle_strip, max_vertices = 4) out;\n"
			<< "layout(location = 0) out vec4 vsColor;\n"
			<< "\n"
			<< pushConstant
			<< "\n"
			<< "void main (void)\n"
			<< "{\n"
			<< "    vec4 quad[4] = vec4[4](vec4(-0.5, 0.5, 0, 1), vec4(-0.5, -0.5, 0, 1), vec4(0.5, 0.5, 0, 1), vec4(0.5, -0.5, 0, 1));\n"
			<< "    for (int i = 0; i < 4; i++)\n"
			<< "    {\n"
			<< "        gl_Position = quad[i] * pc.scale + pc.offset;\n"
			<< "        vsColor     = pc.color;\n"
			<< "        EmitVertex();\n"
			<< "    }\n"
			<< "    EndPrimitive();\n"
			<< "}\n";
		programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
	}

	// Geometry passthrough with layer
	if (m_parameters.enableGeometry)
	{
		std::ostringstream src;
		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
			<< "\n"
			<< "layout(triangles) in;\n"
			<< "layout(triangle_strip, max_vertices = 3) out;\n"
			<< "layout(location = 0) in vec4 position[];\n"
			<< "layout(location = 0) out vec4 vsColor;\n"
			<< "\n"
			<< pushConstant
			<< "\n"
			<< "void main (void)\n"
			<< "{\n"
			<< "    for (int i = 0; i < 3; i++)\n"
			<< "    {\n"
			<< "        gl_Position = position[i];\n"
			<< "        vsColor     = pc.color;\n"
			<< "        gl_Layer    = pc.layer;\n"
			<< "        EmitVertex();\n"
			<< "    }\n"
			<< "    EndPrimitive();\n"
			<< "}\n";
		programCollection.glslSources.add("geomLayer") << glu::GeometrySource(src.str());
	}

	// Tessellation control
	if (m_parameters.enableTessellation)
	{
		std::ostringstream src;
		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
			<< "\n"
			<< "layout(vertices = 4) out;\n"
			<< "layout(location = 0) in vec4 in_color[];\n"
			<< "layout(location = 0) out vec4 out_color[];\n"
			<< "\n"
			<< "void main (void)\n"
			<< "{\n"
			<< "    if (gl_InvocationID == 0)\n"
			<< "    {\n"
			<< "        gl_TessLevelInner[0] = 2.0f;\n"
			<< "        gl_TessLevelInner[1] = 2.0f;\n"
			<< "        gl_TessLevelOuter[0] = 2.0f;\n"
			<< "        gl_TessLevelOuter[1] = 2.0f;\n"
			<< "        gl_TessLevelOuter[2] = 2.0f;\n"
			<< "        gl_TessLevelOuter[3] = 2.0f;\n"
			<< "    }\n"
			<< "    out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
			<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
			<< "}\n";
		programCollection.glslSources.add("tsc") << glu::TessellationControlSource(src.str());
	}

	// Tessellation evaluation
	if (m_parameters.enableTessellation)
	{
		std::ostringstream src;
		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
			<< "\n"
			<< "layout(quads, equal_spacing, ccw) in;\n"
			<< "layout(location = 0) in vec4 in_color[];\n"
			<< "layout(location = 0) out vec4 out_color;\n"
			<< "void main (void)\n"
			<< "{\n"
			<< "    const float u = gl_TessCoord.x;\n"
			<< "    const float v = gl_TessCoord.y;\n"
			<< "    gl_Position = (1 - u) * (1 - v) * gl_in[0].gl_Position + (1 - u) * v * gl_in[1].gl_Position + u * (1 - v) * gl_in[2].gl_Position + u * v * gl_in[3].gl_Position;\n"
			<< "    out_color = in_color[0];\n"
			<< "}\n";
		programCollection.glslSources.add("tse") << glu::TessellationEvaluationSource(src.str());
	}

	// Fragment
	{
		std::ostringstream src;
		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
			<< "#extension GL_EXT_multiview : require\n"
			<< "\n"
			<< "layout(location = 0) in vec4 vsColor;\n"
			<< "layout(location = 0) out vec4 fsColor;\n"
			<< "\n"
			<< "void main (void)\n"
			<< "{\n"
			<< "    fsColor   = vsColor;\n"
			<< "    fsColor.z = 0.15f * gl_ViewIndex;\n"
			<< "}\n";
		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
	}
}

TestInstance*	RandomTestCase::createInstance (Context& context) const
{
	return new DynamicRenderingTestInstance(context, m_parameters);
}

tcu::TestNode* addDynamicRenderingTest (tcu::TestContext& testCtx, TestParameters& parameters)
{
	const std::string testName = "seed" + de::toString(parameters.randomSeed) + (parameters.enableGeometry ? "_geometry" : "") + (parameters.enableTessellation ? "_tessellation" : "");

	return new RandomTestCase(testCtx, testName, "", parameters);
}

} // anonymous

tcu::TestCaseGroup* createDynamicRenderingRandomTests(tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> dynamicRenderingGroup (new tcu::TestCaseGroup(testCtx, "random", "Random dynamic rendering tests"));

	for (auto geometry : {true, false})
		for (auto tessellation : {true, false})
		{
			TestParameters parameters =
			{
				VK_FORMAT_R8G8B8A8_UNORM,
				(UVec2(256, 256)),
				geometry,
				tessellation,
				0u
			};

			for (deUint32 i = 0; i < 100u; i++)
			{
				parameters.randomSeed = i;
				dynamicRenderingGroup->addChild(addDynamicRenderingTest(testCtx, parameters));
			}
		}

	return dynamicRenderingGroup.release();
}

} // renderpass
} // vkt

redpajama_set_name: RedPajamaGithub