Quellcode durchsuchen

Added manual param block generation for DX9 and DX11

BearishSun vor 10 Jahren
Ursprung
Commit
477d430364

+ 61 - 2
BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -1057,8 +1057,67 @@ namespace BansheeEngine
 
 	GpuParamBlockDesc D3D11RenderAPI::generateParamBlockDesc(const String& name, Map<String, GpuParamDataDesc>& params)
 	{
-		// TODO - Not implemented
-		return GpuParamBlockDesc();
+		// TODO - Min 4 bytes, dont cross 16 byte boundary, arrays are always minimum four components
+
+		GpuParamBlockDesc block;
+		block.blockSize = 0;
+		block.isShareable = true;
+		block.name = name;
+		block.slot = 0;
+
+		for (auto& entry : params)
+		{
+			GpuParamDataDesc& param = entry.second;
+
+			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[param.type];
+			UINT32 size = typeInfo.size / 4;
+
+			if (param.arraySize > 1)
+			{
+				// Arrays perform no packing and their elements are always padded and aligned to four component vectors
+				UINT32 alignOffset = size % typeInfo.baseTypeSize;
+				if (alignOffset != 0)
+				{
+					UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
+					size += padding;
+				}
+
+				alignOffset = block.blockSize % typeInfo.baseTypeSize;
+				if (alignOffset != 0)
+				{
+					UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
+					block.blockSize += padding;
+				}
+
+				param.elementSize = size;
+				param.arrayElementStride = size;
+				param.cpuMemOffset = block.blockSize;
+				param.gpuMemOffset = 0;
+
+				block.blockSize += size * param.arraySize;
+			}
+			else
+			{
+				// Pack everything as tightly as possible as long as the data doesn't cross 16 byte boundary
+				UINT32 alignOffset = block.blockSize % 4;
+				if (alignOffset != 0 && size > (4 - alignOffset))
+				{
+					UINT32 padding = (4 - alignOffset);
+					block.blockSize += padding;
+				}
+
+				param.elementSize = size;
+				param.arrayElementStride = size;
+				param.cpuMemOffset = block.blockSize;
+				param.gpuMemOffset = 0;
+
+				block.blockSize += size;
+			}
+
+			param.paramBlockSlot = 0;
+		}
+
+		return block;
 	}
 
 	/************************************************************************/

+ 18 - 65
BansheeD3D9RenderAPI/Include/BsD3D9HLSLParamParser.h

@@ -232,25 +232,21 @@ namespace BansheeEngine
 			{
 			case 1:
 				memberDesc.type = GPDT_INT1;
-				memberDesc.elementSize = 4;
-				memberDesc.arrayElementStride = 4;
 				break;
 			case 2:
 				memberDesc.type = GPDT_INT2;
-				memberDesc.elementSize = 4;
-				memberDesc.arrayElementStride = 4;
 				break;
 			case 3:
 				memberDesc.type = GPDT_INT3;
-				memberDesc.elementSize = 4;
-				memberDesc.arrayElementStride = 4;
 				break;
 			case 4:
 				memberDesc.type = GPDT_INT4;
-				memberDesc.elementSize = 4;
-				memberDesc.arrayElementStride = 4;
 				break;
-			} // columns
+			} 
+
+			memberDesc.elementSize = 4;
+			memberDesc.arrayElementStride = 4;
+
 			break;
 		case D3DXPT_FLOAT:
 			switch(d3dDesc.Class)
@@ -276,55 +272,16 @@ namespace BansheeEngine
 					switch (firstActualDim)
 					{
 					case 2:
-						switch(secondDim)
-						{
-						case 2:
-							memberDesc.elementSize = 8; // HLSL always packs
-							memberDesc.arrayElementStride = 8;
-							break;
-						case 3:
-							memberDesc.elementSize = 8; // HLSL always packs
-							memberDesc.arrayElementStride = 8;
-							break;
-						case 4:
-							memberDesc.elementSize = 8; 
-							memberDesc.arrayElementStride = 8;
-							break;
-						}
+						memberDesc.elementSize = 8; // HLSL always padds regardless of row size
+						memberDesc.arrayElementStride = 8;
 						break;
 					case 3:
-						switch(secondDim)
-						{
-						case 2:
-							memberDesc.elementSize = 12; // HLSL always packs
-							memberDesc.arrayElementStride = 12;
-							break;
-						case 3:
-							memberDesc.elementSize = 12; // HLSL always packs
-							memberDesc.arrayElementStride = 12;
-							break;
-						case 4:
-							memberDesc.elementSize = 12; 
-							memberDesc.arrayElementStride = 12;
-							break;
-						}
+						memberDesc.elementSize = 12; // HLSL always padds regardless of row size
+						memberDesc.arrayElementStride = 12;
 						break;
 					case 4:
-						switch(secondDim)
-						{
-						case 2:
-							memberDesc.elementSize = 16; // HLSL always packs
-							memberDesc.arrayElementStride = 16;
-							break;
-						case 3:
-							memberDesc.elementSize = 16; // HLSL always packs
-							memberDesc.arrayElementStride = 16;
-							break;
-						case 4:
-							memberDesc.elementSize = 16; 
-							memberDesc.arrayElementStride = 16;
-							break;
-						}
+						memberDesc.elementSize = 16; // HLSL always padds regardless of row size
+						memberDesc.arrayElementStride = 16;
 						break;
 
 					}
@@ -382,32 +339,28 @@ namespace BansheeEngine
 				{
 				case 1:
 					memberDesc.type = GPDT_FLOAT1;
-					memberDesc.elementSize = 4;
-					memberDesc.arrayElementStride = 4;
 					break;
 				case 2:
 					memberDesc.type = GPDT_FLOAT2;
-					memberDesc.elementSize = 4;
-					memberDesc.arrayElementStride = 4;
 					break;
 				case 3:
 					memberDesc.type = GPDT_FLOAT3;
-					memberDesc.elementSize = 4;
-					memberDesc.arrayElementStride = 4;
 					break;
 				case 4:
 					memberDesc.type = GPDT_FLOAT4;
-					memberDesc.elementSize = 4;
-					memberDesc.arrayElementStride = 4;
 					break;
-				} // columns
+				}
+
+				memberDesc.elementSize = 4;
+				memberDesc.arrayElementStride = 4;
+
 				break;
 			}
 			break;
 		case D3DXPT_BOOL:
 			memberDesc.type = GPDT_BOOL;
-			memberDesc.elementSize = 1;
-			memberDesc.arrayElementStride = 1;
+			memberDesc.elementSize = 4;
+			memberDesc.arrayElementStride = 4;
 			break;
 		default:
 			break;

+ 31 - 2
BansheeD3D9RenderAPI/Source/BsD3D9RenderAPI.cpp

@@ -1476,8 +1476,37 @@ namespace BansheeEngine
 
 	GpuParamBlockDesc D3D9RenderAPI::generateParamBlockDesc(const String& name, Map<String, GpuParamDataDesc>& params)
 	{
-		// TODO - Not implemented
-		return GpuParamBlockDesc();
+		GpuParamBlockDesc block;
+		block.blockSize = 0;
+		block.isShareable = true;
+		block.name = name;
+		block.slot = 0;
+
+		// DX9 doesn't natively support parameter blocks but Banshee's emulation expects everything to be 16 byte aligned
+		for (auto& entry : params)
+		{
+			GpuParamDataDesc& param = entry.second;
+
+			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[param.type];
+			UINT32 size = typeInfo.size / 4;
+
+			UINT32 alignOffset = size % 4;
+			if (alignOffset != 0)
+				size += 4 - alignOffset;
+
+			param.elementSize = size;
+			param.arrayElementStride = size;
+			param.cpuMemOffset = block.blockSize;
+			param.gpuMemOffset = 0;
+			param.paramBlockSlot = 0;
+
+			if (param.arraySize > 0)
+				block.blockSize += size * param.arraySize;
+			else
+				block.blockSize += size;
+		}
+
+		return block;
 	}
 
 	/************************************************************************/

+ 14 - 20
BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp

@@ -2131,60 +2131,54 @@ namespace BansheeEngine
 		block.name = name;
 		block.slot = 0;
 
-		UINT32 curOffset = 0;
 		for (auto& entry : params)
 		{
 			GpuParamDataDesc& param = entry.second;
 
 			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[param.type];
-			UINT32 sizeBytes = typeInfo.size;
-			UINT32 alignment = typeInfo.alignment;
+			UINT32 size = typeInfo.size / 4;
+			UINT32 alignment = typeInfo.alignment / 4;
 
 			// Fix alignment if needed
-			UINT32 alignOffset = curOffset % alignment;
+			UINT32 alignOffset = block.blockSize % alignment;
 			if (alignOffset != 0)
 			{
 				UINT32 padding = (alignment - alignOffset);
-				curOffset += padding;
 				block.blockSize += padding;
 			}
 
 			if (param.arraySize > 1)
 			{
 				// Array elements are always padded and aligned to vec4
-				alignOffset = sizeBytes % (4 * typeInfo.baseTypeSize);
+				alignOffset = size % typeInfo.baseTypeSize;
 				if (alignOffset != 0)
 				{
-					UINT32 padding = ((4 * typeInfo.baseTypeSize) - alignOffset);
-					sizeBytes += padding;
+					UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
+					size += padding;
 				}
 
-				alignOffset = curOffset % (4 * typeInfo.baseTypeSize);
+				alignOffset = block.blockSize % typeInfo.baseTypeSize;
 				if (alignOffset != 0)
 				{
-					UINT32 padding = ((4 * typeInfo.baseTypeSize) - alignOffset);
-					curOffset += padding;
+					UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
 					block.blockSize += padding;
 				}
 
-				UINT32 size = sizeBytes / 4;
-
 				param.elementSize = size;
 				param.arrayElementStride = size;
-				param.cpuMemOffset = curOffset;
-				param.gpuMemOffset = curOffset;
+				param.cpuMemOffset = block.blockSize;
+				param.gpuMemOffset = 0;
 				
-				curOffset += sizeBytes * param.arraySize;
+				block.blockSize += size * param.arraySize;
 			}
 			else
 			{
-				UINT32 size = sizeBytes / 4;
 				param.elementSize = size;
 				param.arrayElementStride = size;
-				param.cpuMemOffset = curOffset;
-				param.gpuMemOffset = curOffset;
+				param.cpuMemOffset = block.blockSize;
+				param.gpuMemOffset = 0;
 
-				curOffset += sizeBytes;
+				block.blockSize += size;
 			}
 
 			param.paramBlockSlot = 0;

+ 5 - 8
TODOExperimentation.txt

@@ -12,16 +12,13 @@ Assign ViewOrigin, PreViewTranslation, TransViewProj
  - Apply PreViewTranslation when generating world position in shader (multiply 3x3 rotation col by col, then add translation to last col and add that to rotated position)
  - Perhaps do all these modifcations outside of shader (i.e. have the world matrix be pre-transformed)
  - Do this after I have basic rendering working, to avoid additional issues when I'm initially trying to get it to work
-
-Need an easy way to construct parameter buffers in C++
- - PerFrame, PerCamera, PerObject, etc.
- - Currently I need to create a dummy shader just to extract those buffers
- - It would be better if I could manually specify the buffer in C++ and get its parameters
-  - In OpenGL it means I would probably need to use std140 or std430 layouts and modify my parsing code so it uses GL_UNIFORM_BLOCK_DATA_SIZE for retrieving block size
-  - DX11 and OpenGL have different packing rules:
+ 
+ - Finish RenderAPI::generateParamBlockDesc
+   - DX11 and OpenGL have different packing rules:
    - https://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx
    - https://www.safaribooksonline.com/library/view/opengl-programming-guide/9780132748445/app09lev1sec3.html
-   - Finish RenderAPI::generateParamBlockDesc
+ - Replace param buffer generation by using a dummy shader with manual generation
+   - Test if this works on all rendder APIs (initially dont delete the old code so I can compare offsets)
 
 Next week:
  - Deferred base and light passes use different PerCamera buffers, unify them (both in shader and in code)