#include "Shader.h" #include "Text.h" #include "Datei.h" #include "DXBuffer.h" #include #include #include using namespace Framework; // Inhalt der Shader Klasse // Konstruktor Shader::Shader() { type = UNBEKANNT; constBuffers = new RCArray< DXBuffer >(); ref = 1; } // Destruktor Shader::~Shader() { constBuffers->release(); } // Löscht einen constanten Buffer // index: der Index des Buffers, der gelöscht werden soll. Buffer 0 kann nicht gelöscht werden, solange Buffer 1 noch existiert usw. bool Shader::removeConstBuffer( int index ) { if( index < 0 ) return 0; bool ok = 1; constBuffers->set( 0, index ); return 1; } // Kopiert daten in einen constanten buffer // zD3d11Context: Das Context Objekt, das zum kopieren verwendt werden soll // data: Einen zeiger auf en byte Array der größe des Buffers // index: Der Index des Buffers // län: Die Länge der Daten in Bytes (-1 für die maximale größe des Buffers) bool Shader::füllConstBuffer( char *data, int index, int len ) { if( index < 0 ) return 0; DXBuffer * zB = constBuffers->z( index ); if( !zB ) return 0; if( len < 0 ) len = zB->getElementAnzahl() * zB->getElementLength(); zB->setData( data ); zB->copieren( len ); return 1; } // Gibt die Länge eines constanten Buffers zurück // index: Der Index des Buffers int Shader::getConstBufferLänge( int index ) const { if( index < 0 ) return 0; DXBuffer * zB = constBuffers->z( index ); if( !zB ) return 0; return zB->getElementAnzahl() * zB->getElementLength(); } // Gibt den Shadertyp zurück ShaderType Shader::getType() const { return type; } // Erhöht den Reference Counter um 1 // Return: Ein zeiger auf diesen Shader Shader *Shader::getThis() { ref++; return this; } // Verringert den Reference Counter und löscht den Shader, falls der Refeence Counter auf 0 ist // Return: 0 Shader *Shader::release() { ref--; if( !ref ) delete this; return 0; } DX11Shader::DX11Shader( ID3D11Device * device, ID3D11DeviceContext * context ) : Shader() { this->device = device; this->context = context; } DX11Shader::~DX11Shader() {} // erstellt ein constanten Buffer, der constante daten an den Shader übergibt // es können maximal 14 Buffer erstellt werden // zD3d11Device: Das Device, mit dem der Buffer erstellt werden soll // größe: Die größe des buffers in byte // index: Die position des Buffers im Buffer Array. Bereits vorhanderner Buffer wird ersetzt. Buffer 1 kann nicht erstellt werden, wenn Buffer 0 noch nicht erstellt wurde usw. bool DX11Shader::erstelleConstBuffer( int größe, int index ) { if( index < 0 || index >= 14 ) return 0; bool ok = 1; while( ( größe / 16 ) * 16 != größe ) // es sind nur vielfache von 16 als größe erlaubt größe++; constBuffers->set( new DX11Buffer( 1, device, context, D3D11_BIND_CONSTANT_BUFFER ), index ); constBuffers->z( index )->setLength( größe ); return 1; } // Inhalt der PixelShader Klasse // Konstruktor DX11PixelShader::DX11PixelShader( ID3D11Device * device, ID3D11DeviceContext * context ) : DX11Shader( device, context ) { pixelShader = 0; } // Destruktor DX11PixelShader::~DX11PixelShader() { if( pixelShader ) pixelShader->Release(); } // Setzt den Compilierten Shader // bytes: Die Bytes des compilierten codes // length: die Länge des bytearrays // return: true, wenn bytes gültig ist, false sonst bool DX11PixelShader::setCompiledByteArray( unsigned char *bytes, int length ) { HRESULT result = device->CreatePixelShader( bytes, length, 0, &pixelShader ); return result == S_OK; } // Nach dem Aufruf dieser Funktion wird dieser Shader als Pixel Shader benutzt // zD3d11Context: Das Context Objekt, mit dem der Shader verwendet werden soll void DX11PixelShader::benutzeShader() { int maxI = constBuffers->getLastIndex(); for( int i = 0; i <= maxI; i++ ) { if( !constBuffers->z( i ) ) continue; if( !( (DX11Buffer *)constBuffers->z( i ) )->zBuffer() ) constBuffers->z( i )->copieren(); ID3D11Buffer * buf = ( (DX11Buffer *)constBuffers->z( i ) )->zBuffer(); context->PSSetConstantBuffers( i, 1, &buf ); } if( pixelShader ) context->PSSetShader( pixelShader, 0, 0 ); } // Inhalt der VertexShader Klasse // Konstruktor DX11VertexShader::DX11VertexShader( ID3D11Device * device, ID3D11DeviceContext * context ) : DX11Shader( device, context ) { vertexShader = 0; inputLayout = 0; shaderByteBuffer = 0; byteBufferSize = 0; } // Destruktor DX11VertexShader::~DX11VertexShader() { if( vertexShader ) vertexShader->Release(); if( inputLayout ) inputLayout->Release(); } // Setzt den Compilierten Shader // bytes: Die Bytes des compilierten codes // length: die Länge des bytearrays // return: true, wenn bytes gültig ist, false sonst bool DX11VertexShader::setCompiledByteArray( unsigned char *bytes, int length ) { shaderByteBuffer = (unsigned char *)bytes; byteBufferSize = length; HRESULT result = device->CreateVertexShader( bytes, length, 0, &vertexShader ); return result == S_OK; } // erstellt ein InputLayout für den Shader // Darf erst nach compile aufgerufen werden // zD3d11Device: Das Device, mit dem das Layout erstellt werden soll // descArray: Ein Array mit initialisierungsdaten // anz: Die Anzahl der Elemente im Array bool DX11VertexShader::erstelleInputLayout( D3D11_INPUT_ELEMENT_DESC * descArray, int anz ) { if( !shaderByteBuffer ) return 0; if( inputLayout ) inputLayout->Release(); inputLayout = 0; HRESULT res = device->CreateInputLayout( descArray, anz, shaderByteBuffer, byteBufferSize, &inputLayout ); if( res == S_OK ) { shaderByteBuffer = 0; byteBufferSize = 0; } return res == S_OK; } // Nach dem Aufruf dieser Funktion wird dieser Shader als Vertex Shader benutzt // zD3d11Context: Das Context Objekt, mit dem der Shader verwendet werden soll void DX11VertexShader::benutzeShader() { int maxI = constBuffers->getLastIndex(); for( int i = 0; i <= maxI; i++ ) { if( !constBuffers->z( i ) ) continue; if( !( (DX11Buffer *)constBuffers->z( i ) )->zBuffer() ) constBuffers->z( i )->copieren(); ID3D11Buffer * buf = ( (DX11Buffer *)constBuffers->z( i ) )->zBuffer(); context->VSSetConstantBuffers( i, 1, &buf ); } if( inputLayout ) context->IASetInputLayout( inputLayout ); if( vertexShader ) context->VSSetShader( vertexShader, 0, 0 ); } DX12Shader::DX12Shader( ID3D12Device2 * device, ID3D12GraphicsCommandList2 * list ) { shaderByteBuffer = 0; byteBufferSize = 0; this->device = device; this->list = list; } DX12Shader::~DX12Shader() { delete[] shaderByteBuffer; } // erstellt ein constanten Buffer, der constante daten an den Shader übergibt // es können maximal 14 Buffer erstellt werden // zD3d11Device: Das Device, mit dem der Buffer erstellt werden soll // size: Die größe des buffers in byte // index: Die position des Buffers im Buffer Array. Bereits vorhanderner Buffer wird ersetzt. Buffer 1 kann nicht erstellt werden, wenn Buffer 0 noch nicht erstellt wurde usw. bool DX12Shader::erstelleConstBuffer( int size, int index ) { if( index < 0 || index >= 14 ) return 0; while( ( size / 256 ) * 256 != size ) size++; constBuffers->set( new DX12Buffer( 1, device, list, D3D12_RESOURCE_FLAG_NONE ), index ); constBuffers->z( index )->setLength( size ); constBuffers->z( index )->copieren(); return 1; } // Setzt den Compilierten Shader // zD3d11Device: Das Device, mit welchem der Shader erstellt werden soll // bytes: Die Bytes des compilierten codes // length: die Länge des bytearrays // return: true, wenn bytes gültig ist, false sonst bool DX12Shader::setCompiledByteArray( unsigned char *bytes, int length ) { delete[] shaderByteBuffer; shaderByteBuffer = new unsigned char[ length ]; memcpy( shaderByteBuffer, bytes, length ); byteBufferSize = length; return 1; } // Nach dem Aufruf dieser Funktion wird dieser Shader als Pixel Shader benutzt // zD3d11Context: Das Context Objekt, mit dem der Shader verwendet werden soll void DX12Shader::benutzeShader() { // not needet in DirectX 12 } // gibt die compilierten bytes zurück unsigned char *DX12Shader::getCompiledShader() const { return shaderByteBuffer; } // gitbt die anzahl der compilierten bytes zurück int DX12Shader::getCompiledLength() const { return byteBufferSize; } // Erstellt den RootParameter zu einem constanten buffer // index: Der Index des Buffers // view: enthält nach dem Aufruf die position und größe des buffers im speicher void DX12Shader::getViewDesc( int index, D3D12_CONSTANT_BUFFER_VIEW_DESC &view ) { DX12Buffer *zB = (DX12Buffer *)constBuffers->z( index ); if( !zB ) return; view.SizeInBytes = zB->getElementAnzahl() * zB->getElementLength(); view.BufferLocation = zB->zBuffer()->GetGPUVirtualAddress(); } DX12PixelShader::DX12PixelShader( ID3D12Device2 * device, ID3D12GraphicsCommandList2 * list ) : DX12Shader( device, list ) {} // Konstruktor DX12VertexShader::DX12VertexShader( ID3D12Device2 * device, ID3D12GraphicsCommandList2 * list ) : DX12Shader( device, list ) { inputLayout = 0; inputLayoutSize = 0; } // Destruktor DX12VertexShader::~DX12VertexShader() { delete[] inputLayout; } // erstellt ein InputLayout für den Shader // Darf erst nach compile aufgerufen werden // zD3d11Device: Das Device, mit dem das Layout erstellt werden soll // descArray: Ein Array mit initialisierungsdaten // anz: Die Anzahl der Elemente im Array bool DX12VertexShader::erstelleInputLayout( D3D12_INPUT_ELEMENT_DESC * descArray, int anz ) { delete[] inputLayout; inputLayout = new D3D12_INPUT_ELEMENT_DESC[ anz ]; memcpy( inputLayout, descArray, anz * sizeof( D3D12_INPUT_ELEMENT_DESC ) ); inputLayoutSize = anz; return 1; } // Gint die Anzahl an eingabeparametern des Shaders zurück int DX12VertexShader::getInputLayoutSize() const { return inputLayoutSize; } // Gibt eine Liste mit formaten für jeden Eingabewert zurück D3D12_INPUT_ELEMENT_DESC *DX12VertexShader::zInputLayout() const { return inputLayout; }