Show More
Commit Description:
Fix syntax error.
Commit Description:
Fix syntax error.
References:
File last commit:
Show/Diff file:
Action:
FNA/lib/FNA3D/src/FNA3D_PipelineCache.c
259 lines | 6.4 KiB | text/x-c | CLexer
259 lines | 6.4 KiB | text/x-c | CLexer
r690 | /* FNA3D - 3D Graphics Library for FNA | |||
* | ||||
* Copyright (c) 2020-2022 Ethan Lee | ||||
* | ||||
* This software is provided 'as-is', without any express or implied warranty. | ||||
* In no event will the authors be held liable for any damages arising from | ||||
* the use of this software. | ||||
* | ||||
* Permission is granted to anyone to use this software for any purpose, | ||||
* including commercial applications, and to alter it and redistribute it | ||||
* freely, subject to the following restrictions: | ||||
* | ||||
* 1. The origin of this software must not be misrepresented; you must not | ||||
* claim that you wrote the original software. If you use this software in a | ||||
* product, an acknowledgment in the product documentation would be | ||||
* appreciated but is not required. | ||||
* | ||||
* 2. Altered source versions must be plainly marked as such, and must not be | ||||
* misrepresented as being the original software. | ||||
* | ||||
* 3. This notice may not be removed or altered from any source distribution. | ||||
* | ||||
* Ethan "flibitijibibo" Lee <flibitijibibo@flibitijibibo.com> | ||||
* | ||||
*/ | ||||
#include "FNA3D_PipelineCache.h" | ||||
#include <SDL.h> | ||||
/* Packed Pipeline States */ | ||||
PackedState GetPackedBlendState(FNA3D_BlendState blendState) | ||||
{ | ||||
PackedState result; | ||||
int32_t funcs = ( | ||||
blendState.alphaBlendFunction << 4 | ||||
| blendState.colorBlendFunction << 0 | ||||
); | ||||
int32_t blendsAndColorWritesChannels = ( | ||||
blendState.alphaDestinationBlend << 28 | ||||
| blendState.alphaSourceBlend << 24 | ||||
| blendState.colorDestinationBlend << 20 | ||||
| blendState.colorSourceBlend << 16 | ||||
| blendState.colorWriteEnable << 12 | ||||
| blendState.colorWriteEnable1 << 8 | ||||
| blendState.colorWriteEnable2 << 4 | ||||
| blendState.colorWriteEnable3 << 0 | ||||
); | ||||
int32_t blendFactorPacked = ( | ||||
blendState.blendFactor.r << 0 | ||||
| blendState.blendFactor.g << 8 | ||||
| blendState.blendFactor.b << 16 | ||||
| blendState.blendFactor.a << 24 | ||||
); | ||||
result.a = ( | ||||
(uint64_t) funcs << 32 | | ||||
(uint64_t) blendsAndColorWritesChannels | ||||
); | ||||
result.b = ( | ||||
(uint64_t) blendState.multiSampleMask << 32 | | ||||
(uint64_t) blendFactorPacked | ||||
); | ||||
return result; | ||||
} | ||||
PackedState GetPackedDepthStencilState(FNA3D_DepthStencilState dsState) | ||||
{ | ||||
PackedState result; | ||||
int32_t packedProperties = ( | ||||
dsState.depthBufferEnable << 30 | ||||
| dsState.depthBufferWriteEnable << 29 | ||||
| dsState.stencilEnable << 28 | ||||
| dsState.twoSidedStencilMode << 27 | ||||
| dsState.depthBufferFunction << 24 | ||||
| dsState.stencilFunction << 21 | ||||
| dsState.ccwStencilFunction << 18 | ||||
| dsState.stencilPass << 15 | ||||
| dsState.stencilFail << 12 | ||||
| dsState.stencilDepthBufferFail << 9 | ||||
| dsState.ccwStencilPass << 6 | ||||
| dsState.ccwStencilFail << 3 | ||||
| dsState.ccwStencilDepthBufferFail | ||||
); | ||||
result.a = ( | ||||
(uint64_t) dsState.stencilMask << 32 | | ||||
(uint64_t) packedProperties | ||||
); | ||||
result.b = ( | ||||
(uint64_t) dsState.referenceStencil << 32 | | ||||
(uint64_t) dsState.stencilWriteMask | ||||
); | ||||
return result; | ||||
} | ||||
#define FLOAT_TO_UINT64(f) (uint64_t) *((uint32_t*) &f) | ||||
PackedState GetPackedRasterizerState(FNA3D_RasterizerState rastState, float bias) | ||||
{ | ||||
PackedState result; | ||||
int32_t packedProperties = ( | ||||
rastState.multiSampleAntiAlias << 4 | ||||
| rastState.scissorTestEnable << 3 | ||||
| rastState.fillMode << 2 | ||||
| rastState.cullMode | ||||
); | ||||
result.a = (uint64_t) packedProperties; | ||||
result.b = ( | ||||
FLOAT_TO_UINT64(rastState.slopeScaleDepthBias) << 32 | | ||||
FLOAT_TO_UINT64(bias) | ||||
); | ||||
return result; | ||||
} | ||||
PackedState GetPackedSamplerState(FNA3D_SamplerState samplerState) | ||||
{ | ||||
PackedState result; | ||||
int32_t packedProperties = ( | ||||
samplerState.filter << 6 | ||||
| samplerState.addressU << 4 | ||||
| samplerState.addressV << 2 | ||||
| samplerState.addressW | ||||
); | ||||
result.a = ( | ||||
(uint64_t) samplerState.maxAnisotropy << 32 | | ||||
(uint64_t) packedProperties | ||||
); | ||||
result.b = ( | ||||
(uint64_t) samplerState.maxMipLevel << 32 | | ||||
FLOAT_TO_UINT64(samplerState.mipMapLevelOfDetailBias) | ||||
); | ||||
return result; | ||||
} | ||||
#undef FLOAT_TO_UINT64 | ||||
void* PackedStateArray_Fetch(PackedStateArray arr, PackedState key) | ||||
{ | ||||
int32_t i; | ||||
for (i = 0; i < arr.count; i += 1) | ||||
{ | ||||
if ( key.a == arr.elements[i].key.a && | ||||
key.b == arr.elements[i].key.b ) | ||||
{ | ||||
return arr.elements[i].value; | ||||
} | ||||
} | ||||
return NULL; | ||||
} | ||||
void PackedStateArray_Insert(PackedStateArray *arr, PackedState key, void* value) | ||||
{ | ||||
PackedStateMap map; | ||||
map.key.a = key.a; | ||||
map.key.b = key.b; | ||||
map.value = value; | ||||
EXPAND_ARRAY_IF_NEEDED(arr, 4, PackedStateMap) | ||||
arr->elements[arr->count] = map; | ||||
arr->count += 1; | ||||
} | ||||
/* Vertex Buffer Bindings */ | ||||
static inline uint32_t GetPackedVertexElement(FNA3D_VertexElement element) | ||||
{ | ||||
/* FIXME: Backport this to FNA! */ | ||||
/* Technically element.offset is an int32, but geez, | ||||
* if you're using more than 2^20 bytes, you've got | ||||
* bigger problems to worry about. | ||||
* -caleb | ||||
*/ | ||||
return ( | ||||
element.offset << 12 | ||||
| element.vertexElementFormat << 8 | ||||
| element.vertexElementUsage << 4 | ||||
| element.usageIndex | ||||
); | ||||
} | ||||
static uint32_t HashVertexBufferBindings( | ||||
FNA3D_VertexBufferBinding *bindings, | ||||
int32_t numBindings | ||||
) { | ||||
int32_t i, j; | ||||
uint32_t hash = numBindings; | ||||
/* The algorithm for this hashing function | ||||
* is taken from Josh Bloch's "Effective Java". | ||||
* (https://stackoverflow.com/a/113600/12492383) | ||||
*/ | ||||
const uint32_t HASH_FACTOR = 37; | ||||
for (i = 0; i < numBindings; i += 1) | ||||
{ | ||||
for (j = 0; j < bindings[i].vertexDeclaration.elementCount; j += 1) | ||||
{ | ||||
hash = hash * HASH_FACTOR + GetPackedVertexElement( | ||||
bindings[i].vertexDeclaration.elements[j] | ||||
); | ||||
} | ||||
hash = hash * HASH_FACTOR + bindings[i].vertexDeclaration.vertexStride; | ||||
hash = hash * HASH_FACTOR + bindings[i].instanceFrequency; | ||||
} | ||||
return hash; | ||||
} | ||||
void* PackedVertexBufferBindingsArray_Fetch( | ||||
PackedVertexBufferBindingsArray arr, | ||||
FNA3D_VertexBufferBinding *bindings, | ||||
int32_t numBindings, | ||||
void* vertexShader, | ||||
int32_t *outIndex, | ||||
uint32_t *outHash | ||||
) { | ||||
int32_t i; | ||||
PackedVertexBufferBindings other; | ||||
uint32_t hash = HashVertexBufferBindings(bindings, numBindings); | ||||
void* result = NULL; | ||||
for (i = 0; i < arr.count; i += 1) | ||||
{ | ||||
other = arr.elements[i].key; | ||||
if (vertexShader == other.vertexShader && hash == other.hash) | ||||
{ | ||||
result = arr.elements[i].value; | ||||
break; | ||||
} | ||||
} | ||||
*outIndex = i; | ||||
*outHash = hash; | ||||
return result; | ||||
} | ||||
void PackedVertexBufferBindingsArray_Insert( | ||||
PackedVertexBufferBindingsArray *arr, | ||||
FNA3D_VertexBufferBinding *bindings, | ||||
int32_t numBindings, | ||||
void* vertexShader, | ||||
void* value | ||||
) { | ||||
PackedVertexBufferBindingsMap map; | ||||
EXPAND_ARRAY_IF_NEEDED(arr, 4, PackedVertexBufferBindingsMap) | ||||
map.key.vertexShader = vertexShader; | ||||
map.key.hash = HashVertexBufferBindings(bindings, numBindings); | ||||
map.value = value; | ||||
arr->elements[arr->count] = map; | ||||
arr->count += 1; | ||||
} | ||||
/* vim: set noexpandtab shiftwidth=8 tabstop=8: */ | ||||