Seite 87 von 254

Re: Jammer-Thread

Verfasst: 25.09.2012, 18:39
von eXile
Ja, die Productivity Tools kommen schon Anfang Oktober, aber die Information, dass wohl weitere Features kommen werden, gab es schon früher. Aber ich schreibe auch gerne: Die Neuigkeit ist sooo eine Woche alt. ;) Ähnlich wie mit dem ganzen Clang-Kram, den ich schon ausprobiert hatte, und dem Heini seinen Blog unter Pseudonym die Kommentare vollgepflastert habe.

Die ganzen Developer Previews sind ja gerade dafür da, alle persönlichen Einstellungen und Extensions so schnell auf Visual Studio 2012 zu portieren, damit man direkt am ersten Tag des Releases damit loslegen kann. Gut gemacht, Nvidia, oder so! :evil:

Mit dem verlinkten Workaround bin ich unter Visual Studio 2012 was die Extensions angeht (auch dank AutoScroll, GoToDefinition und der bekannten Git-Extension) feature-complete. Wobei, die Seitentaster meiner Maus funktionieren noch nicht richtig, fällt mir beim Schreiben gerade auf. Die meisten Extensions haben da auch ein relativ komisches Verhalten.

Oder vielleicht bin ich einfach nur am Extreme-Early-Adopting, und ziehe mir alle neuen Previews sofort durch die Nase:

[youtube]sXasCjUTNpE[/youtube]

Are you ready for Visual Studio 2012?

Re: Jammer-Thread

Verfasst: 26.09.2012, 11:32
von CodingCat
eXile hat geschrieben:Die ganzen Developer Previews sind ja gerade dafür da, alle persönlichen Einstellungen und Extensions so schnell auf Visual Studio 2012 zu portieren, damit man direkt am ersten Tag des Releases damit loslegen kann. Gut gemacht, Nvidia, oder so! :evil:
Wie sieht es eigentlich mit den Visual Studio DirectX Graphics Diagnostics aus, zu gebrauchen?

Außerdem: Bin ich zu blöd, oder lässt sich das Find-Fenster (Ctrl+F) ums Verrecken nicht dazu bringen, das gerade markierte Wort zu übernehmen, ohne dass ich dieses immer händisch dort hinein pasten muss?

Re: Jammer-Thread

Verfasst: 26.09.2012, 11:35
von Schrompf
Pix -> Debug this Pixel -> Debug Pixel -> ungelogen 20min Wartezeit, bis PIX den dazugehörigen Pixelshader gefunden hat.

Re: Jammer-Thread

Verfasst: 26.09.2012, 11:45
von dot
CodingCat hat geschrieben:Wie sieht es eigentlich mit den Visual Studio DirectX Graphics Diagnostics aus, zu gebrauchen?
Jo, is ganz nett, im Prinzip halt einfach PIX in VS integriert. Man muss nur aufpassen, niemals swapchain->ResizeBuffers() mit DXGI_FORMAT_UNKNOWN aufrufen, sobald du das tust, kann er irgendwie nix mehr capturen...ewig hab ich den gesucht...

Re: Jammer-Thread

Verfasst: 26.09.2012, 16:17
von CodingCat

Code: Alles auswählen

new(info.ConstantBuffers.get() + info.ConstantBufferCount) ConstantBufferInfo()
Wenn mich nicht alles täuscht, müsste das Objekt danach vollständig initialisiert sein, non-POD Members mit Default-Konstruktor und POD Members mit Null. Jetzt, ratet mal, was Visual C++ 2012 tut ...

SOLL ICH JETZT ERNSTHAFT FÜR 20 STRUKTUREN VOLLKOMMEN REDUNDANDE KONSTRUKTOREN SCHREIBEN?!

Oh, und der Fehler wird schon seit Jahren gemeldet. Wundert sich noch wer, dass die entsprechenden Bug Reports gelöscht wurden? WTF! Manchmal glaube ich, irgendein Vollidiot bei Microsoft will uns mit aller Macht daran hindern, bessere Programme zu schreiben als der nutzlose, verfettete, unlesbare und höchst instabile Müll, den sie selbst täglich produzieren und uns dann noch teuer verkaufen wollen.

Re: Jammer-Thread

Verfasst: 26.09.2012, 23:06
von CodingCat
Wer immer das binäre Shader/Effect Format von DirectX entworfen hat, wollte seinen Arbeitsplatz auf alle Ewigkeit sichern.

Re: Jammer-Thread

Verfasst: 26.09.2012, 23:40
von dot
CodingCat hat geschrieben:Wer immer das binäre Shader/Effect Format von DirectX entworfen hat, wollte seinen Arbeitsplatz auf alle Ewigkeit sichern.
Hast du eine offizielle Doku dafür gefunden? Afaik gibt's kaum mehr als einen Header im WDK...

Re: Jammer-Thread

Verfasst: 26.09.2012, 23:52
von CodingCat
Genau damit arbeite ich. Ein ganzer Tag Arbeit, 600 Zeilen Code und ich habe gerade mal Konstanten, Constant Buffers und Annotations. Das Miese an der Sache ist, dass alles in exakt der richtigen Reihenfolge gelesen werden muss. Keine Chunks, keine Einsprungadressen. Insbesondere heißt das, dass ich alles verarbeiten muss, egal, ob ich davon etwas wissen will. Und damit das richtig Spaß macht, liegen die Daten schön polymorph durcheinander, keine Sortierung nach Typ ...

Re: Jammer-Thread

Verfasst: 27.09.2012, 09:44
von Krishty
Falls es dir hilft: AMDs GPU Shader Analyzer (müsste auch ohne AMD-Karte laufen) hat für Shader eine Echtzeitvorschau des entstehenden Textes – überwiegend des GPU-Maschinentexts, aber es gibt auch eine Vorschau für Direct3D-Bytecode (nicht binär, sondern menschenlesbar).

Falls du also ganz schnell wissen möchtest, was für Konstrukte dich für bestimmte Shader erwarten, oder generell zum Debuggen, kann ich das nur empfehlen.

Re: Jammer-Thread

Verfasst: 27.09.2012, 19:35
von CodingCat
Danke, bis jetzt ließ sich alles einigermaßen aus den offiziellen Effects11 Sources erkennen. Glaubt man diesen Sources, kann man in Effects übrigens allem alles zuweisen, z.B. Variablen in Render State Blocks (die dann bei Veränderung zur Laufzeit neu erzeugt werden, wie es aussieht O_o), Objekte anderen Objekten. Davon habe ich trotz intensivster Effekt-Nutzung die letzten Jahre kein einziges Mal Gebrauch gemacht. Ich liebe es, wenn ich riesige Code-Abschnitte des Original-Quellcodes durch eine einzige Unsupported Exception ersetzen kann.

Noch die State-, Shader- und Resource-Bindings in den Passes, dann bin ich durch. Es sei denn, Interfaces werden tatsächlich in Realität eingesetzt?!

Re: Jammer-Thread

Verfasst: 27.09.2012, 19:43
von dot
CodingCat hat geschrieben:Noch die State-, Shader- und Resource-Bindings in den Passes, dann bin ich durch. Es sei denn, Interfaces werden tatsächlich in Realität eingesetzt?!
Dynamic Shader Linkage verwendet wohl so gut wie niemand, zumindest meinem Gefühl nach. Vermutlich aus Performancegründen!?

Re: Jammer-Thread

Verfasst: 27.09.2012, 20:21
von CodingCat
Ich hätte eher auf Kompatibilitätsgründe getippt. Ich habe allerdings nicht die leiseste Ahnung, wie langsam/schnell das ist, weil ich es noch nie mit auch nur einem Wort in irgendeiner Präsentation erwähnt gesehen habe. Ist mir vorerst Recht, dann werde ich evtl. noch heute Nacht fertig.

Re: Jammer-Thread

Verfasst: 28.09.2012, 01:27
von CodingCat
Der FX-Compiler speichert Shader-Zuweisungen auf 5 verschiedene Arten, in Worten: fünf. Konstante (nur für NULL), Variable, Variable mit konstantem Index, Inline, Inline Erweitert. Theoretisch gibt es sogar noch weitere, z.B. Variable mit variablem Index, diese unterstützt jedoch nicht mal mehr der offizielle Effects11 Source Code. Die muss damals echt was geritten haben, als sie für DirectX 9 eine ganze FX-VM implementiert hatten. Die Nachwehen spürt man noch heute.

Re: Jammer-Thread

Verfasst: 28.09.2012, 16:19
von CodingCat
Array-New- und Array-Delete-Operator lassen sich in C++ global überhaupt nicht sinnvoll überladen. Wie man es auch dreht, man landet unweigerlich in einer Zugriffsverletzung (es gibt keine Möglichkeit, überladene delete[]s aufzurufen und auch keine Möglichkeit, diese durch Funktionen zu ersetzen).

Umso erstaunlicher ist, dass Visual C++ die Konstruktion von Arrays ohne die Überladung des new[]-Operators trotzdem erlaubt, und zwar in diesem Fall einfach mit dem überladenen nicht-Array-New-Operator. Da der nicht-Array-New-Operator keine Schweinereien mit dem Zeiger treibt, lässt sich in diesem Fall auch problemlos ein Array-Delete-Ersatz in Form einer Funktion schreiben.

Diese Verhalten ist auf jeden Fall sinnvoll, ob es standardkonform ist, kann ich im Moment nicht sagen.

Re: Jammer-Thread

Verfasst: 28.09.2012, 20:39
von dot
CodingCat hat geschrieben:Umso erstaunlicher ist, dass Visual C++ die Konstruktion von Arrays ohne die Überladung des new[]-Operators trotzdem erlaubt, und zwar in diesem Fall einfach mit dem überladenen nicht-Array-New-Operator. Da der nicht-Array-New-Operator keine Schweinereien mit dem Zeiger treibt, lässt sich in diesem Fall auch problemlos ein Array-Delete-Ersatz in Form einer Funktion schreiben.

Diese Verhalten ist auf jeden Fall sinnvoll, ob es standardkonform ist, kann ich im Moment nicht sagen.
Ich bin mir grad nicht ganz sicher, was genau du damit meinst...meinst du dass MSVC den normalen operator new verwendet, wenn kein operator new[] zur Verfügung steht? Das wäre wohl ganz sicher nicht standardkonform. Sicher dass er das tut und nicht vielleicht irgendeinen operator new[] der stdlib nimmt?

Re: Jammer-Thread

Verfasst: 28.09.2012, 20:53
von CodingCat
Ja, ganz sicher tut es das, bin im ASM durchgesteppt. Die Konstruktionsschleife wird wie bei operator new[] mitsamt Ausnahmebehandlung generiert, nur die Allokation geht im Gegensatz zu operator new[] ohne Offset an operator new. Und das ist bezüglich globaler Überladung von Array-New tatsächlich der einzig sinnvolle Weg, Standardkonformität hin oder her. Globale Überladung von operator new[] könnte (und sollte) man somit wohl sogar verbieten.

Re: Jammer-Thread

Verfasst: 28.09.2012, 23:10
von Krishty
Falls ich mich recht irre, sprechen wir über den von mir verhassten scalar vector c'tor iterator, oder wie dieses ominöse Symbol non grata heißt. Der schleppt übrigens auch die Ausnahmebehandlung mit, wenn in den aufgerufenen Operatoren und K’toren überhaupt keine Ausnahmen geworfen werden können (entsprechender Bug-Report gelöscht). Hoffentlich kriege ich Clang bald zum Linken.

Re: Jammer-Thread

Verfasst: 29.09.2012, 00:35
von CodingCat
Der FX-Binärcode kennt unzählige Blockformate für jede noch so mickrige Variation im Datenlayout. Trotzdem muss ich ausgerechnet die ekligen Stream-Out-Strings noch beim Laden von Hand parsen, weil der Compiler diese einfach unverdaut in Textform speichert.

Oh und: Jedes gute Unterprogramm beginnt mit einer Endlosschleife und endet mit einem Exit-Label. Ich liebe die Referenzimplementierung. Und nein, es ist kein C-Code. Im Gegenteil, sämtliche Parameterübergabe und Rückgabe erfolgt ausschließlich über den Zustand der jeweils umschließenden Klasse. Exzessive Objektorientierung muss man das wohl nennen. Oder: Das Schlimmste aus beiden Welten.

Re: Jammer-Thread

Verfasst: 29.09.2012, 02:09
von kaiserludi
Gerade mal ein kleiens Testprogramm geschrieben:

Code: Alles auswählen

#include <malloc.h>

inline void* operator new(unsigned int size)
{
	return malloc(size);
}

inline void operator delete(void *ptr)
{
	free(ptr);
}

inline void* operator new[](unsigned int size)
{
	return malloc(size);
}

inline void operator delete[](void *ptr)
{
	free(ptr);
}

class Test
{
public:
	Test(void);
	~Test(void);
private:
	long long* mTest;
};

Test::Test(void)
{
	mTest = new long long[8];
}

Test::~Test(void)
{
	delete[] mTest;
}

int main(void)
{
	int* arr = new int[16];
	for(int i=0; i<16; ++i)
		arr[i] = i;
	delete[] arr;
	Test* test = new Test[32];
	delete[] test;
}
Läuft bei mir im Homeoffice unter VC++ 2k8 völlig problemlos.

Re: Jammer-Thread

Verfasst: 29.09.2012, 02:43
von CodingCat
Liegt daran, dass du nicht überlädst, sondern falsch überschreibst/ersetzt. Die Signatur ist sinnvollerweise festgeschrieben auf den Größentyp size_t. Sofern deine Operatoren überhaupt aufgerufen werden, ist das ein Fehler im Compiler, ansonsten nur deiner. inline ist an dieser Stelle übrigens auch nicht erlaubt. Überladen wäre so etwas:

Code: Alles auswählen

void* operator new[](size_t size, Allocator &allocator)
{
   // Achtung, muss bei Fehler Exception werfen!
   return allocator.Allocate(size);
}

void operator delete[](void *p, Allocator &allocator)
{
   allocator.Free(p);
}

int main()
{
   NaKlasse *array = new(myAllocator) NaKlasse[6];
   // array lässt sich hier unter keinen Umständen sauber freigeben.
}
Warum? Weil wir keine Möglichkeit haben, unsere delete[]-Überladung mit einem delete[]-Ausdruck aufzurufen. array zeigt aber mit an Sicherheit grenzender Wahrscheinlichkeit NICHT auf den Anfang des Speicherbereichs, weswegen auch manuelle Destruktion mit anschließendem myAllocator.Free() nicht funktioniert. Witzigerweise schluckt Visual C++ folgendes, womit manuelles Free() wieder möglich wird:

Code: Alles auswählen

// new[] und delete[] bewusst NICHT überladen. Führt dazu, dass VC++ einfach diese beiden Überladungen ohne Zeiger-Offset aufruft.
void* operator new(size_t size, Allocator &allocator)
{
   // Achtung, muss bei Fehler Exception werfen!
   return allocator.Allocate(size);
}

void operator delete(void *p, Allocator &allocator)
{
   allocator.Free(p);
}

int main()
{
   NaKlasse *array = new(myAllocator) NaKlasse[6];
   // Jetzt geht:
   for (int i = 6; i-- > 0; )
      array[i].~NaKlasse();
   myAllocator.Free(array);
}

Re: Jammer-Thread

Verfasst: 29.09.2012, 03:31
von kaiserludi
Argh, da erkläre ich letztens noch einem Kollegen den Unterschied zwischen Überladen und Überschreiben und ann passiert mir sowas...
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer..... The value of the result is implementation-defined, and its type (an unsigned integer type) is size_t (ISO C99 Section 6.5.3.4)
In VC++ 32Bit ist der Rückgabetyp von sizeof() genauso groß wie unsigned int. Damit sind in desem Fall unsigned int und size_t gleich bedeutend und es liegt erst ein Fehler vor, wenn man eine Implementation vorliegen hat, in der sie verschiedene Größen haben.

Tante Edith sagt:

Code: Alles auswählen

if(typeid(unsigned int) == typeid(size_t))
gibt in codepad.org sogar true zurück ist also in der Implementation tatsächlich ein und der gleiche Typ.

Re: Jammer-Thread

Verfasst: 29.09.2012, 03:38
von eXile
Dürfe ich fragen, was gegen ::operator delete[] spricht?

Als Freund kompilierbaren Minimalcodes habe ich mal runtergetippselt:

Code: Alles auswählen

#include "Windows.h"
#include <iostream>

using namespace std;

class Allocator
{
public:
	Allocator()
	  : myHeapHandle(::GetProcessHeap())
	{
		return;
	}

	void * Allocate(size_t theSize)
	{
		return ::HeapAlloc(myHeapHandle, 0, theSize);
	}

	void Free(void * thePointer)
	{
		if(thePointer)
			::HeapFree(myHeapHandle, 0, thePointer);
	}

private:
	::HANDLE myHeapHandle;
};

struct NaKlasse
{
	int i;
	double d;
};

void* operator new[](size_t size, Allocator &allocator)
{
	return allocator.Allocate(size);
}

void operator delete[](void *p, Allocator &allocator)
{
	allocator.Free(p);
}

int main(int argc, char * argv[])
{
	Allocator myAllocator;
	NaKlasse *array = new(myAllocator) NaKlasse[6];

	for(auto i = 0u; i < 6; i++)
		array[i].~NaKlasse();

	::operator delete[](array, myAllocator);

	return 0;
}

Re: Jammer-Thread

Verfasst: 29.09.2012, 10:08
von Krishty
kaiserludi hat geschrieben:In VC++ 32Bit ist der Rückgabetyp von sizeof() genauso groß wie unsigned int. Damit sind in desem Fall unsigned int und size_t gleich bedeutend
kaiserludi hat geschrieben:

Code: Alles auswählen

if(typeid(unsigned int) == typeid(size_t))
gibt in codepad.org sogar true zurück ist also in der Implementation tatsächlich ein und der gleiche Typ.
Auf codepad vielleicht; aber wer sagt, dass dein persönlicher Compiler in deiner persönlichen Version nicht unsigned long einsetzt? Vielleicht auch gleich groß; anderer Typ; große Scheiße.

Re: Jammer-Thread

Verfasst: 29.09.2012, 11:41
von CodingCat
eXile hat geschrieben:Dürfe ich fragen, was gegen ::operator delete[] spricht?

Als Freund kompilierbaren Minimalcodes habe ich mal runtergetippselt:

Code: Alles auswählen

#include "Windows.h"
#include <iostream>

using namespace std;

class Allocator
{
public:
	Allocator()
	  : myHeapHandle(::GetProcessHeap())
	{
		return;
	}

	void * Allocate(size_t theSize)
	{
		return ::HeapAlloc(myHeapHandle, 0, theSize);
	}

	void Free(void * thePointer)
	{
		if(thePointer)
			::HeapFree(myHeapHandle, 0, thePointer);
	}

private:
	::HANDLE myHeapHandle;
};

struct NaKlasse
{
	int i;
	double d;
};

void* operator new[](size_t size, Allocator &allocator)
{
	return allocator.Allocate(size);
}

void operator delete[](void *p, Allocator &allocator)
{
	allocator.Free(p);
}

int main(int argc, char * argv[])
{
	Allocator myAllocator;
	NaKlasse *array = new(myAllocator) NaKlasse[6];

	for(auto i = 0u; i < 6; i++)
		array[i].~NaKlasse();

	::operator delete[](array, myAllocator);

	return 0;
}
::operator delete[] ist nur ein Funktionsaufruf und macht das Zeigeroffset zur Arrayverwaltung nicht rückgängig. In ::operator delete[] kommt also ein anderer Zeiger rein als in ::operator new[] raus.

Re: Jammer-Thread

Verfasst: 29.09.2012, 11:49
von Krishty
Darum zum tausendsten Mal: Placement new in einer Schleife auf selber allokierten Speicher ist seit über einem Jahr das einzige, was ich noch benutze. (Halbwegs in Funktionen versteckt aber.)

Re: Jammer-Thread

Verfasst: 29.09.2012, 14:19
von eXile
CodingCat hat geschrieben:In ::operator delete[] kommt also ein anderer Zeiger rein als in ::operator new[] raus.
Aber warum sagt mir dann mein Debugger:

Code: Alles auswählen

operator new[] returned 0x00507ad0 void *
p 0x00507ad0 void *

Re: Jammer-Thread

Verfasst: 29.09.2012, 14:24
von CodingCat
Weil deine Klasse zufällig trivial ist, keine Destruktion und somit auch kein Bookkeeping erfordert.

Re: Jammer-Thread

Verfasst: 29.09.2012, 15:40
von dot
CodingCat hat geschrieben:Witzigerweise schluckt Visual C++ folgendes, womit manuelles Free() wieder möglich wird: [...]
Das sollte imo auf keinen Fall standardkonform sein. Davon abgesehen, sollte die Reihenfolge der Destruktoraufrufe wohl genau umgekehrt sein... ;)

Re: Jammer-Thread

Verfasst: 29.09.2012, 15:53
von CodingCat
Sehr guter Hinweis, habs oben in meinem Beitrag gefixt. Und ja, ich habe auch nichts dergleichen im Standard gefunden. Was schade ist, denn genau dieses Verhalten bräuchte man für Placement-Array-New.

Re: Jammer-Thread

Verfasst: 29.09.2012, 16:08
von dot
CodingCat hat geschrieben:Sehr guter Hinweis, habs oben in meinem Beitrag gefixt.
Sry, aber ich glaub ich muss leider nochmal: Sollte wohl >= 0 heißen... :P
CodingCat hat geschrieben:Und ja, ich habe auch nichts dergleichen im Standard gefunden. [...]
Der Standard sagt imo explizit, dass das falsch ist, vielleicht sollte man den Bug reporten?
ISO/IEC 14882:2011 §5.3.4/8 hat geschrieben:If the allocated type is an array type, the allocation function’s name is operator new[] and the deallocation function’s name is operator delete[].
CodingCat hat geschrieben:[...] Was schade ist, denn genau dieses Verhalten bräuchte man für Placement-Array-New.
Naja, imo solltest du das von dir gewünschte Verhalten doch einfach mit einem std::vector und entsprechendem Allocator hinbekommen!?