Merge remote-tracking branch 'origin/master' into 1.9
This commit is contained in:
@@ -166,14 +166,14 @@ CreateAssetResult CreateMaterial::Create(CreateAssetContext& context)
|
||||
|
||||
// Diffuse + Mask
|
||||
ShaderGraphNode<>* diffuseTextureNode;
|
||||
AddInput(layer, meta, MaterialGraphBoxes::Color, options.Diffuse.Texture, options.Diffuse.Color, Color::White, Float2::Zero, &diffuseTextureNode);
|
||||
AddInput(layer, meta, MaterialGraphBoxes::Color, options.Diffuse.Texture, options.Diffuse.Color, Color::Black, Float2::Zero, &diffuseTextureNode);
|
||||
if (diffuseTextureNode && options.Diffuse.HasAlphaMask)
|
||||
{
|
||||
CONNECT(layer->Root->Boxes[static_cast<int32>(MaterialGraphBoxes::Mask)], diffuseTextureNode->Boxes[5]);
|
||||
}
|
||||
|
||||
// Emissive
|
||||
AddInput(layer, meta, MaterialGraphBoxes::Emissive, options.Emissive.Texture, options.Emissive.Color, Color::Transparent, Float2(0, 200));
|
||||
AddInput(layer, meta, MaterialGraphBoxes::Emissive, options.Emissive.Texture, options.Emissive.Color, Color::Black, Float2(0, 200));
|
||||
|
||||
// Opacity
|
||||
AddInput(layer, meta, MaterialGraphBoxes::Opacity, options.Opacity.Texture, options.Opacity.Value, 1.0f, Float2(0, 400));
|
||||
|
||||
@@ -40,13 +40,28 @@
|
||||
// True if allow graphics profile events and markers
|
||||
#define GPU_ALLOW_PROFILE_EVENTS (!BUILD_RELEASE)
|
||||
|
||||
// True if allow hardware tessellation shaders (Hull and Domain shaders)
|
||||
#ifndef GPU_ALLOW_TESSELLATION_SHADERS
|
||||
#define GPU_ALLOW_TESSELLATION_SHADERS 1
|
||||
#endif
|
||||
|
||||
// True if allow geometry shaders
|
||||
#ifndef GPU_ALLOW_GEOMETRY_SHADERS
|
||||
#define GPU_ALLOW_GEOMETRY_SHADERS 1
|
||||
#endif
|
||||
|
||||
// Enable/disable creating GPU resources on separate threads (otherwise only the main thread can be used)
|
||||
#define GPU_ENABLE_ASYNC_RESOURCES_CREATION 1
|
||||
|
||||
// Enable/disable force shaders recompilation
|
||||
#define GPU_FORCE_RECOMPILE_SHADERS 0
|
||||
|
||||
// Default back buffer pixel format
|
||||
// Define default back buffer(s) format
|
||||
#ifndef GPU_BACK_BUFFER_PIXEL_FORMAT
|
||||
#define GPU_BACK_BUFFER_PIXEL_FORMAT PixelFormat::B8G8R8A8_UNorm
|
||||
#endif
|
||||
|
||||
// Default depth buffer pixel format
|
||||
#ifndef GPU_DEPTH_BUFFER_PIXEL_FORMAT
|
||||
#define GPU_DEPTH_BUFFER_PIXEL_FORMAT PixelFormat::D32_Float
|
||||
#endif
|
||||
@@ -62,11 +77,6 @@
|
||||
#define GPU_MAX_TEXTURE_MIP_LEVELS 15
|
||||
#define GPU_MAX_TEXTURE_ARRAY_SIZE 1024
|
||||
|
||||
// Define default back buffer(s) format
|
||||
#ifndef GPU_BACK_BUFFER_PIXEL_FORMAT
|
||||
#define GPU_BACK_BUFFER_PIXEL_FORMAT PixelFormat::B8G8R8A8_UNorm
|
||||
#endif
|
||||
|
||||
// Validate configuration
|
||||
#if !ENABLE_ASSERTION
|
||||
#undef GPU_ENABLE_ASSERTION
|
||||
|
||||
@@ -147,6 +147,7 @@ bool DeferredMaterialShader::Load()
|
||||
psDesc.DepthEnable = false;
|
||||
}
|
||||
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
// Check if use tessellation (both material and runtime supports it)
|
||||
const bool useTess = _info.TessellationMode != TessellationMethod::None && GPUDevice::Instance->Limits.HasTessellation;
|
||||
if (useTess)
|
||||
@@ -154,6 +155,7 @@ bool DeferredMaterialShader::Load()
|
||||
psDesc.HS = _shader->GetHS("HS");
|
||||
psDesc.DS = _shader->GetDS("DS");
|
||||
}
|
||||
#endif
|
||||
|
||||
// GBuffer Pass
|
||||
psDesc.VS = _shader->GetVS("VS");
|
||||
|
||||
@@ -115,6 +115,7 @@ bool DeformableMaterialShader::Load()
|
||||
psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
|
||||
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
|
||||
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
// Check if use tessellation (both material and runtime supports it)
|
||||
const bool useTess = _info.TessellationMode != TessellationMethod::None && GPUDevice::Instance->Limits.HasTessellation;
|
||||
if (useTess)
|
||||
@@ -122,6 +123,7 @@ bool DeformableMaterialShader::Load()
|
||||
psDesc.HS = _shader->GetHS("HS");
|
||||
psDesc.DS = _shader->GetDS("DS");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_EDITOR
|
||||
if (_shader->HasShader("PS_QuadOverdraw"))
|
||||
|
||||
@@ -134,6 +134,7 @@ bool ForwardMaterialShader::Load()
|
||||
psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
|
||||
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
|
||||
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
// Check if use tessellation (both material and runtime supports it)
|
||||
const bool useTess = _info.TessellationMode != TessellationMethod::None && GPUDevice::Instance->Limits.HasTessellation;
|
||||
if (useTess)
|
||||
@@ -141,6 +142,7 @@ bool ForwardMaterialShader::Load()
|
||||
psDesc.HS = _shader->GetHS("HS");
|
||||
psDesc.DS = _shader->GetDS("DS");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_EDITOR
|
||||
if (_shader->HasShader("PS_QuadOverdraw"))
|
||||
|
||||
@@ -137,6 +137,7 @@ bool TerrainMaterialShader::Load()
|
||||
psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
|
||||
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
|
||||
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
// Check if use tessellation (both material and runtime supports it)
|
||||
const bool useTess = _info.TessellationMode != TessellationMethod::None && GPUDevice::Instance->Limits.HasTessellation;
|
||||
if (useTess)
|
||||
@@ -144,6 +145,7 @@ bool TerrainMaterialShader::Load()
|
||||
psDesc.HS = _shader->GetHS("HS");
|
||||
psDesc.DS = _shader->GetDS("DS");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Support blending but then use only emissive channel
|
||||
switch (_info.BlendMode)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/// <summary>
|
||||
/// Describes a single skeleton node data. Used by the runtime.
|
||||
/// </summary>
|
||||
API_STRUCT() struct SkeletonNode
|
||||
API_STRUCT() struct FLAXENGINE_API SkeletonNode
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(SkeletonNode);
|
||||
|
||||
@@ -34,7 +34,7 @@ API_STRUCT() struct SkeletonNode
|
||||
/// <summary>
|
||||
/// Describes a single skeleton bone data. Used by the runtime. Skeleton bones are subset of the skeleton nodes collection that are actually used by the skinned model meshes.
|
||||
/// </summary>
|
||||
API_STRUCT() struct SkeletonBone
|
||||
API_STRUCT() struct FLAXENGINE_API SkeletonBone
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(SkeletonBone);
|
||||
|
||||
@@ -71,7 +71,7 @@ struct TIsPODType<SkeletonBone>
|
||||
/// <remarks>
|
||||
/// Bones are ordered so that parents always come first, allowing for hierarchical updates in a simple loop.
|
||||
/// </remarks>
|
||||
class SkeletonData
|
||||
class FLAXENGINE_API SkeletonData
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
@@ -129,6 +129,14 @@ bool GPUShader::Create(MemoryReadStream& stream)
|
||||
GPUShaderProgram* shader = CreateGPUShaderProgram(type, initializer, cache, cacheSize, stream);
|
||||
if (shader == nullptr)
|
||||
{
|
||||
#if !GPU_ALLOW_TESSELLATION_SHADERS
|
||||
if (type == ShaderStage::Hull || type == ShaderStage::Domain)
|
||||
continue;
|
||||
#endif
|
||||
#if !GPU_ALLOW_GEOMETRY_SHADERS
|
||||
if (type == ShaderStage::Geometry)
|
||||
continue;
|
||||
#endif
|
||||
LOG(Error, "Failed to create {} Shader program '{}' ({}).", ::ToString(type), String(initializer.Name), name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,11 @@ public:
|
||||
/// <returns>The shader object.</returns>
|
||||
API_FUNCTION() FORCE_INLINE GPUShaderProgramHS* GetHS(const StringAnsiView& name, int32 permutationIndex = 0) const
|
||||
{
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
return static_cast<GPUShaderProgramHS*>(GetShader(ShaderStage::Hull, name, permutationIndex));
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -114,7 +118,11 @@ public:
|
||||
/// <returns>The shader object.</returns>
|
||||
API_FUNCTION() FORCE_INLINE GPUShaderProgramDS* GetDS(const StringAnsiView& name, int32 permutationIndex = 0) const
|
||||
{
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
return static_cast<GPUShaderProgramDS*>(GetShader(ShaderStage::Domain, name, permutationIndex));
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -125,7 +133,11 @@ public:
|
||||
/// <returns>The shader object.</returns>
|
||||
API_FUNCTION() FORCE_INLINE GPUShaderProgramGS* GetGS(const StringAnsiView& name, int32 permutationIndex = 0) const
|
||||
{
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
return static_cast<GPUShaderProgramGS*>(GetShader(ShaderStage::Geometry, name, permutationIndex));
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -113,8 +113,9 @@ bool StreamingTexture::Create(const TextureHeader& header)
|
||||
if (_isBlockCompressed)
|
||||
{
|
||||
// Ensure that streaming doesn't go too low because the hardware expects the texture to be min in size of compressed texture block
|
||||
const int32 blockSize = PixelFormatExtensions::ComputeBlockSize(_header.Format);
|
||||
int32 lastMip = header.MipLevels - 1;
|
||||
while ((header.Width >> lastMip) < 4 && (header.Height >> lastMip) < 4 && lastMip > 0)
|
||||
while ((header.Width >> lastMip) < blockSize && (header.Height >> lastMip) < blockSize && lastMip > 0)
|
||||
lastMip--;
|
||||
_minMipCountBlockCompressed = Math::Min(header.MipLevels - lastMip + 1, header.MipLevels);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@ GPUContextDX11::GPUContextDX11(GPUDeviceDX11* device, ID3D11DeviceContext* conte
|
||||
, _omDirtyFlag(false)
|
||||
, _rtCount(0)
|
||||
, _rtDepth(nullptr)
|
||||
, _srDirtyFlag(false)
|
||||
, _srMaskDirtyGraphics(0)
|
||||
, _srMaskDirtyCompute(0)
|
||||
, _uaDirtyFlag(false)
|
||||
, _cbDirtyFlag(false)
|
||||
, _currentState(nullptr)
|
||||
@@ -80,8 +81,9 @@ void GPUContextDX11::FrameBegin()
|
||||
// Setup
|
||||
_omDirtyFlag = false;
|
||||
_uaDirtyFlag = false;
|
||||
_srDirtyFlag = false;
|
||||
_cbDirtyFlag = false;
|
||||
_srMaskDirtyGraphics = 0;
|
||||
_srMaskDirtyCompute = 0;
|
||||
_rtCount = 0;
|
||||
_currentState = nullptr;
|
||||
_rtDepth = nullptr;
|
||||
@@ -97,9 +99,13 @@ void GPUContextDX11::FrameBegin()
|
||||
CurrentRasterizerState = nullptr;
|
||||
CurrentDepthStencilState = nullptr;
|
||||
CurrentVS = nullptr;
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
CurrentHS = nullptr;
|
||||
CurrentDS = nullptr;
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
CurrentGS = nullptr;
|
||||
#endif
|
||||
CurrentPS = nullptr;
|
||||
CurrentCS = nullptr;
|
||||
CurrentPrimitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
||||
@@ -117,7 +123,9 @@ void GPUContextDX11::FrameBegin()
|
||||
_device->_samplerShadowLinear
|
||||
};
|
||||
_context->VSSetSamplers(0, ARRAY_COUNT(samplers), samplers);
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
_context->DSSetSamplers(0, ARRAY_COUNT(samplers), samplers);
|
||||
#endif
|
||||
_context->PSSetSamplers(0, ARRAY_COUNT(samplers), samplers);
|
||||
_context->CSSetSamplers(0, ARRAY_COUNT(samplers), samplers);
|
||||
}
|
||||
@@ -282,13 +290,18 @@ void GPUContextDX11::SetStencilRef(uint32 value)
|
||||
|
||||
void GPUContextDX11::ResetSR()
|
||||
{
|
||||
_srDirtyFlag = false;
|
||||
_srMaskDirtyGraphics = MAX_uint32;
|
||||
_srMaskDirtyCompute = MAX_uint32;
|
||||
Platform::MemoryClear(_srHandles, sizeof(_srHandles));
|
||||
|
||||
_context->VSSetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles);
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
_context->HSSetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles);
|
||||
_context->DSSetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles);
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
_context->GSSetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles);
|
||||
#endif
|
||||
_context->PSSetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles);
|
||||
_context->CSSetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles);
|
||||
}
|
||||
@@ -308,9 +321,13 @@ void GPUContextDX11::ResetCB()
|
||||
Platform::MemoryClear(_cbHandles, sizeof(_cbHandles));
|
||||
|
||||
_context->VSSetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles);
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
_context->HSSetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles);
|
||||
_context->DSSetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles);
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
_context->GSSetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles);
|
||||
#endif
|
||||
_context->PSSetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles);
|
||||
_context->CSSetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles);
|
||||
}
|
||||
@@ -339,7 +356,8 @@ void GPUContextDX11::BindSR(int32 slot, GPUResourceView* view)
|
||||
auto handle = view ? ((IShaderResourceDX11*)view->GetNativePtr())->SRV() : nullptr;
|
||||
if (_srHandles[slot] != handle)
|
||||
{
|
||||
_srDirtyFlag = true;
|
||||
_srMaskDirtyGraphics |= 1 << slot;
|
||||
_srMaskDirtyCompute |= 1 << slot;
|
||||
_srHandles[slot] = handle;
|
||||
if (view)
|
||||
*view->LastRenderTime = _lastRenderTime;
|
||||
@@ -397,7 +415,9 @@ void GPUContextDX11::BindSampler(int32 slot, GPUSampler* sampler)
|
||||
{
|
||||
const auto samplerDX11 = sampler ? static_cast<GPUSamplerDX11*>(sampler)->SamplerState : nullptr;
|
||||
_context->VSSetSamplers(slot, 1, &samplerDX11);
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
_context->DSSetSamplers(slot, 1, &samplerDX11);
|
||||
#endif
|
||||
_context->PSSetSamplers(slot, 1, &samplerDX11);
|
||||
_context->CSSetSamplers(slot, 1, &samplerDX11);
|
||||
}
|
||||
@@ -536,9 +556,13 @@ void GPUContextDX11::SetState(GPUPipelineState* state)
|
||||
ID3D11RasterizerState* rasterizerState = nullptr;
|
||||
ID3D11DepthStencilState* depthStencilState = nullptr;
|
||||
GPUShaderProgramVSDX11* vs = nullptr;
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
GPUShaderProgramHSDX11* hs = nullptr;
|
||||
GPUShaderProgramDSDX11* ds = nullptr;
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
GPUShaderProgramGSDX11* gs = nullptr;
|
||||
#endif
|
||||
GPUShaderProgramPSDX11* ps = nullptr;
|
||||
D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
||||
|
||||
@@ -552,9 +576,13 @@ void GPUContextDX11::SetState(GPUPipelineState* state)
|
||||
|
||||
ASSERT(_currentState->VS != nullptr);
|
||||
vs = _currentState->VS;
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
hs = _currentState->HS;
|
||||
ds = _currentState->DS;
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
gs = _currentState->GS;
|
||||
#endif
|
||||
ps = _currentState->PS;
|
||||
|
||||
primitiveTopology = _currentState->PrimitiveTopology;
|
||||
@@ -588,6 +616,7 @@ void GPUContextDX11::SetState(GPUPipelineState* state)
|
||||
_context->VSSetShader(vs ? vs->GetBufferHandleDX11() : nullptr, nullptr, 0);
|
||||
_context->IASetInputLayout(vs ? vs->GetInputLayoutDX11() : nullptr);
|
||||
}
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
if (CurrentHS != hs)
|
||||
{
|
||||
#if DX11_CLEAR_SR_ON_STAGE_DISABLE
|
||||
@@ -610,6 +639,8 @@ void GPUContextDX11::SetState(GPUPipelineState* state)
|
||||
CurrentDS = ds;
|
||||
_context->DSSetShader(ds ? ds->GetBufferHandleDX11() : nullptr, nullptr, 0);
|
||||
}
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
if (CurrentGS != gs)
|
||||
{
|
||||
#if DX11_CLEAR_SR_ON_STAGE_DISABLE
|
||||
@@ -621,6 +652,7 @@ void GPUContextDX11::SetState(GPUPipelineState* state)
|
||||
CurrentGS = gs;
|
||||
_context->GSSetShader(gs ? gs->GetBufferHandleDX11() : nullptr, nullptr, 0);
|
||||
}
|
||||
#endif
|
||||
if (CurrentPS != ps)
|
||||
{
|
||||
#if DX11_CLEAR_SR_ON_STAGE_DISABLE
|
||||
@@ -667,7 +699,9 @@ void GPUContextDX11::ClearState()
|
||||
_device->_samplerShadowPCF
|
||||
};
|
||||
_context->VSSetSamplers(0, ARRAY_COUNT(samplers), samplers);
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
_context->DSSetSamplers(0, ARRAY_COUNT(samplers), samplers);
|
||||
#endif
|
||||
_context->PSSetSamplers(0, ARRAY_COUNT(samplers), samplers);
|
||||
_context->CSSetSamplers(0, ARRAY_COUNT(samplers), samplers);
|
||||
#endif
|
||||
@@ -802,25 +836,32 @@ void GPUContextDX11::CopySubresource(GPUResource* dstResource, uint32 dstSubreso
|
||||
|
||||
void GPUContextDX11::flushSRVs()
|
||||
{
|
||||
if (_srDirtyFlag)
|
||||
#define FLUSH_STAGE(STAGE) if (Current##STAGE) _context->STAGE##SetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles)
|
||||
if (CurrentCS)
|
||||
{
|
||||
_srDirtyFlag = false;
|
||||
|
||||
// Flush with the driver
|
||||
// TODO: don't bind SRV to all stages and all slots (use mask for bind diff?)
|
||||
#define FLUSH_STAGE(STAGE) \
|
||||
if (Current##STAGE) \
|
||||
{ \
|
||||
_context->STAGE##SetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles); \
|
||||
}
|
||||
FLUSH_STAGE(VS);
|
||||
FLUSH_STAGE(HS);
|
||||
FLUSH_STAGE(DS);
|
||||
FLUSH_STAGE(GS);
|
||||
FLUSH_STAGE(PS);
|
||||
FLUSH_STAGE(CS);
|
||||
#undef FLUSH_STAGE
|
||||
if (_srMaskDirtyCompute)
|
||||
{
|
||||
_srMaskDirtyCompute = 0;
|
||||
FLUSH_STAGE(CS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_srMaskDirtyGraphics)
|
||||
{
|
||||
_srMaskDirtyGraphics = 0;
|
||||
FLUSH_STAGE(VS);
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
FLUSH_STAGE(HS);
|
||||
FLUSH_STAGE(DS);
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
FLUSH_STAGE(GS);
|
||||
#endif
|
||||
FLUSH_STAGE(PS);
|
||||
}
|
||||
}
|
||||
#undef FLUSH_STAGE
|
||||
}
|
||||
|
||||
void GPUContextDX11::flushUAVs()
|
||||
@@ -846,15 +887,15 @@ void GPUContextDX11::flushCBs()
|
||||
|
||||
// Flush with the driver
|
||||
// TODO: don't bind CBV to all stages and all slots (use mask for bind diff? eg. cache mask from last flush and check if there is a diff + include mask from diff slots?)
|
||||
#define FLUSH_STAGE(STAGE) \
|
||||
if (Current##STAGE) \
|
||||
{ \
|
||||
_context->STAGE##SetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles); \
|
||||
}
|
||||
#define FLUSH_STAGE(STAGE) if (Current##STAGE) _context->STAGE##SetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles)
|
||||
FLUSH_STAGE(VS);
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
FLUSH_STAGE(HS);
|
||||
FLUSH_STAGE(DS);
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
FLUSH_STAGE(GS);
|
||||
#endif
|
||||
FLUSH_STAGE(PS);
|
||||
FLUSH_STAGE(CS);
|
||||
#undef FLUSH_STAGE
|
||||
|
||||
@@ -32,7 +32,8 @@ private:
|
||||
ID3D11RenderTargetView* _rtHandles[GPU_MAX_RT_BINDED];
|
||||
|
||||
// Shader Resources
|
||||
bool _srDirtyFlag;
|
||||
uint32 _srMaskDirtyGraphics;
|
||||
uint32 _srMaskDirtyCompute;
|
||||
ID3D11ShaderResourceView* _srHandles[GPU_MAX_SR_BINDED];
|
||||
|
||||
// Unordered Access
|
||||
@@ -55,9 +56,13 @@ private:
|
||||
ID3D11RasterizerState* CurrentRasterizerState;
|
||||
ID3D11DepthStencilState* CurrentDepthStencilState;
|
||||
GPUShaderProgramVSDX11* CurrentVS;
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
GPUShaderProgramHSDX11* CurrentHS;
|
||||
GPUShaderProgramDSDX11* CurrentDS;
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
GPUShaderProgramGSDX11* CurrentGS;
|
||||
#endif
|
||||
GPUShaderProgramPSDX11* CurrentPS;
|
||||
GPUShaderProgramCSDX11* CurrentCS;
|
||||
D3D11_PRIMITIVE_TOPOLOGY CurrentPrimitiveTopology;
|
||||
|
||||
@@ -342,8 +342,8 @@ bool GPUDeviceDX11::Init()
|
||||
D3D11_FEATURE_DATA_D3D11_OPTIONS2 featureDataD3D11Options2 = {};
|
||||
_device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS2, &featureDataD3D11Options2, sizeof(featureDataD3D11Options2));
|
||||
limits.HasCompute = d3D10XHardwareOptions.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x != 0;
|
||||
limits.HasTessellation = true;
|
||||
limits.HasGeometryShaders = true;
|
||||
limits.HasTessellation = GPU_ALLOW_TESSELLATION_SHADERS;
|
||||
limits.HasGeometryShaders = GPU_ALLOW_GEOMETRY_SHADERS;
|
||||
limits.HasInstancing = true;
|
||||
limits.HasVolumeTextureRendering = true;
|
||||
limits.HasDrawIndirect = true;
|
||||
@@ -367,7 +367,7 @@ bool GPUDeviceDX11::Init()
|
||||
{
|
||||
limits.HasCompute = false;
|
||||
limits.HasTessellation = false;
|
||||
limits.HasGeometryShaders = true;
|
||||
limits.HasGeometryShaders = GPU_ALLOW_GEOMETRY_SHADERS;
|
||||
limits.HasInstancing = true;
|
||||
limits.HasVolumeTextureRendering = false;
|
||||
limits.HasDrawIndirect = false;
|
||||
|
||||
@@ -8,9 +8,13 @@ void GPUPipelineStateDX11::OnReleaseGPU()
|
||||
{
|
||||
BlendState = nullptr;
|
||||
VS = nullptr;
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
HS = nullptr;
|
||||
DS = nullptr;
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
GS = nullptr;
|
||||
#endif
|
||||
PS = nullptr;
|
||||
}
|
||||
|
||||
@@ -30,9 +34,13 @@ bool GPUPipelineStateDX11::Init(const Description& desc)
|
||||
|
||||
// Cache shaders
|
||||
VS = (GPUShaderProgramVSDX11*)desc.VS;
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
HS = desc.HS ? (GPUShaderProgramHSDX11*)desc.HS : nullptr;
|
||||
DS = desc.DS ? (GPUShaderProgramDSDX11*)desc.DS : nullptr;
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
GS = desc.GS ? (GPUShaderProgramGSDX11*)desc.GS : nullptr;
|
||||
#endif
|
||||
PS = desc.PS ? (GPUShaderProgramPSDX11*)desc.PS : nullptr;
|
||||
|
||||
// Primitive Topology
|
||||
@@ -44,8 +52,10 @@ bool GPUPipelineStateDX11::Init(const Description& desc)
|
||||
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
|
||||
};
|
||||
PrimitiveTopology = D3D11_primTypes[static_cast<int32>(desc.PrimitiveTopology)];
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
if (HS)
|
||||
PrimitiveTopology = (D3D11_PRIMITIVE_TOPOLOGY)((int32)D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (HS->GetControlPointsCount() - 1));
|
||||
#endif
|
||||
|
||||
// States
|
||||
DepthStencilStateIndex = static_cast<int32>(desc.DepthFunc) + (desc.DepthEnable ? 0 : 9) + (desc.DepthWriteEnable ? 0 : 18);
|
||||
|
||||
@@ -19,9 +19,13 @@ public:
|
||||
int32 RasterizerStateIndex;
|
||||
ID3D11BlendState* BlendState = nullptr;
|
||||
GPUShaderProgramVSDX11* VS = nullptr;
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
GPUShaderProgramHSDX11* HS = nullptr;
|
||||
GPUShaderProgramDSDX11* DS = nullptr;
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
GPUShaderProgramGSDX11* GS = nullptr;
|
||||
#endif
|
||||
GPUShaderProgramPSDX11* PS = nullptr;
|
||||
D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
shader = New<GPUShaderProgramVSDX11>(initializer, buffer, inputLayout, inputLayoutSize);
|
||||
break;
|
||||
}
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
case ShaderStage::Hull:
|
||||
{
|
||||
// Read control points
|
||||
@@ -118,6 +119,15 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
shader = New<GPUShaderProgramDSDX11>(initializer, buffer);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
case ShaderStage::Hull:
|
||||
{
|
||||
int32 controlPointsCount;
|
||||
stream.ReadInt32(&controlPointsCount);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
case ShaderStage::Geometry:
|
||||
{
|
||||
// Create shader
|
||||
@@ -129,6 +139,7 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
shader = New<GPUShaderProgramGSDX11>(initializer, buffer);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case ShaderStage::Pixel:
|
||||
{
|
||||
// Create shader
|
||||
|
||||
@@ -122,6 +122,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
/// <summary>
|
||||
/// Hull Shader for DirectX 11 backend.
|
||||
/// </summary>
|
||||
@@ -159,7 +160,9 @@ public:
|
||||
{
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
/// <summary>
|
||||
/// Geometry Shader for DirectX 11 backend.
|
||||
/// </summary>
|
||||
@@ -177,6 +180,7 @@ public:
|
||||
{
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Pixel Shader for DirectX 11 backend.
|
||||
|
||||
@@ -373,8 +373,8 @@ bool GPUDeviceDX12::Init()
|
||||
{
|
||||
auto& limits = Limits;
|
||||
limits.HasCompute = true;
|
||||
limits.HasTessellation = true;
|
||||
limits.HasGeometryShaders = true;
|
||||
limits.HasTessellation = GPU_ALLOW_TESSELLATION_SHADERS;
|
||||
limits.HasGeometryShaders = GPU_ALLOW_GEOMETRY_SHADERS;
|
||||
limits.HasInstancing = true;
|
||||
limits.HasVolumeTextureRendering = true;
|
||||
limits.HasDrawIndirect = true;
|
||||
|
||||
@@ -163,9 +163,13 @@ bool GPUPipelineStateDX12::Init(const Description& desc)
|
||||
if (shader->Header.UaDimensions[i]) \
|
||||
Header.UaDimensions[i] = shader->Header.UaDimensions[i]; \
|
||||
}
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
INIT_SHADER_STAGE(HS, GPUShaderProgramHSDX12);
|
||||
INIT_SHADER_STAGE(DS, GPUShaderProgramDSDX12);
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
INIT_SHADER_STAGE(GS, GPUShaderProgramGSDX12);
|
||||
#endif
|
||||
INIT_SHADER_STAGE(VS, GPUShaderProgramVSDX12);
|
||||
INIT_SHADER_STAGE(PS, GPUShaderProgramPSDX12);
|
||||
const static D3D12_PRIMITIVE_TOPOLOGY_TYPE primTypes1[] =
|
||||
@@ -184,11 +188,13 @@ bool GPUPipelineStateDX12::Init(const Description& desc)
|
||||
};
|
||||
psDesc.PrimitiveTopologyType = primTypes1[(int32)desc.PrimitiveTopology];
|
||||
PrimitiveTopology = primTypes2[(int32)desc.PrimitiveTopology];
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
if (desc.HS)
|
||||
{
|
||||
psDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
|
||||
PrimitiveTopology = (D3D_PRIMITIVE_TOPOLOGY)((int32)D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (desc.HS->GetControlPointsCount() - 1));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Depth State
|
||||
psDesc.DepthStencilState.DepthEnable = !!desc.DepthEnable;
|
||||
|
||||
@@ -85,6 +85,7 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
|
||||
shader = New<GPUShaderProgramVSDX12>(initializer, header, cacheBytes, cacheSize, inputLayout, inputLayoutSize);
|
||||
break;
|
||||
}
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
case ShaderStage::Hull:
|
||||
{
|
||||
int32 controlPointsCount;
|
||||
@@ -97,11 +98,21 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
|
||||
shader = New<GPUShaderProgramDSDX12>(initializer, header, cacheBytes, cacheSize);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
case ShaderStage::Hull:
|
||||
{
|
||||
int32 controlPointsCount;
|
||||
stream.ReadInt32(&controlPointsCount);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
case ShaderStage::Geometry:
|
||||
{
|
||||
shader = New<GPUShaderProgramGSDX12>(initializer, header, cacheBytes, cacheSize);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case ShaderStage::Pixel:
|
||||
{
|
||||
shader = New<GPUShaderProgramPSDX12>(initializer, header, cacheBytes, cacheSize);
|
||||
|
||||
@@ -79,6 +79,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
/// <summary>
|
||||
/// Hull Shader for DirectX 12 backend.
|
||||
/// </summary>
|
||||
@@ -105,7 +106,9 @@ public:
|
||||
{
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
/// <summary>
|
||||
/// Geometry Shader for DirectX 12 backend.
|
||||
/// </summary>
|
||||
@@ -118,6 +121,7 @@ public:
|
||||
{
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Pixel Shader for DirectX 12 backend.
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
|
||||
#if GRAPHICS_API_VULKAN && PLATFORM_ANDROID
|
||||
|
||||
// Support more backbuffers in case driver decides to use more
|
||||
#define VULKAN_BACK_BUFFERS_COUNT_MAX 8
|
||||
|
||||
/// <summary>
|
||||
/// The implementation for the Vulkan API support for Android platform.
|
||||
/// </summary>
|
||||
|
||||
@@ -25,21 +25,25 @@ namespace DescriptorSet
|
||||
enum Stage
|
||||
{
|
||||
// Vertex shader stage
|
||||
Vertex = 0,
|
||||
Vertex,
|
||||
// Pixel shader stage
|
||||
Pixel = 1,
|
||||
Pixel,
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
// Geometry shader stage
|
||||
Geometry = 2,
|
||||
Geometry,
|
||||
#endif
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
// Hull shader stage
|
||||
Hull = 3,
|
||||
Hull,
|
||||
// Domain shader stage
|
||||
Domain = 4,
|
||||
Domain,
|
||||
#endif
|
||||
// Graphics pipeline stages count
|
||||
GraphicsStagesCount = 5,
|
||||
GraphicsStagesCount,
|
||||
// Compute pipeline slot
|
||||
Compute = 0,
|
||||
// The maximum amount of slots for all stages
|
||||
Max = 5,
|
||||
Max = GraphicsStagesCount,
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -1686,15 +1686,15 @@ bool GPUDeviceVulkan::Init()
|
||||
|
||||
auto& limits = Limits;
|
||||
limits.HasCompute = GetShaderProfile() == ShaderProfile::Vulkan_SM5 && PhysicalDeviceLimits.maxComputeWorkGroupCount[0] >= GPU_MAX_CS_DISPATCH_THREAD_GROUPS && PhysicalDeviceLimits.maxComputeWorkGroupCount[1] >= GPU_MAX_CS_DISPATCH_THREAD_GROUPS;
|
||||
#if PLATFORM_MAC || PLATFORM_IOS
|
||||
limits.HasTessellation = false; // MoltenVK has artifacts when using tess
|
||||
#else
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
limits.HasTessellation = !!PhysicalDeviceFeatures.tessellationShader && PhysicalDeviceLimits.maxBoundDescriptorSets > (uint32_t)DescriptorSet::Domain;
|
||||
#endif
|
||||
#if PLATFORM_ANDROID || PLATFORM_IOS
|
||||
limits.HasGeometryShaders = false; // Don't even try GS on mobile
|
||||
#else
|
||||
limits.HasGeometryShaders = !!PhysicalDeviceFeatures.geometryShader;
|
||||
limits.HasTessellation = false;
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
limits.HasGeometryShaders = !!PhysicalDeviceFeatures.geometryShader && PhysicalDeviceLimits.maxBoundDescriptorSets > (uint32_t)DescriptorSet::Geometry;
|
||||
#else
|
||||
limits.HasGeometryShaders = false;
|
||||
#endif
|
||||
limits.HasInstancing = true;
|
||||
limits.HasVolumeTextureRendering = true;
|
||||
|
||||
@@ -133,17 +133,19 @@ PipelineLayoutVulkan* GPUPipelineStateVulkan::GetLayout()
|
||||
return _layout;
|
||||
|
||||
DescriptorSetLayoutInfoVulkan descriptorSetLayoutInfo;
|
||||
|
||||
#define INIT_SHADER_STAGE(set, bit) \
|
||||
if (DescriptorInfoPerStage[DescriptorSet::set]) \
|
||||
descriptorSetLayoutInfo.AddBindingsForStage(bit, DescriptorSet::set, DescriptorInfoPerStage[DescriptorSet::set])
|
||||
INIT_SHADER_STAGE(Vertex, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
INIT_SHADER_STAGE(Hull, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
|
||||
INIT_SHADER_STAGE(Domain, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
INIT_SHADER_STAGE(Geometry, VK_SHADER_STAGE_GEOMETRY_BIT);
|
||||
#endif
|
||||
INIT_SHADER_STAGE(Pixel, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
#undef INIT_SHADER_STAGE
|
||||
|
||||
_layout = _device->GetOrCreateLayout(descriptorSetLayoutInfo);
|
||||
ASSERT(_layout);
|
||||
DescriptorSetsLayout = &_layout->DescriptorSetLayout;
|
||||
@@ -253,9 +255,13 @@ bool GPUPipelineStateVulkan::Init(const Description& desc)
|
||||
stage.pName = desc.type->GetName().Get(); \
|
||||
}
|
||||
INIT_SHADER_STAGE(VS, Vertex, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
INIT_SHADER_STAGE(HS, Hull, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
|
||||
INIT_SHADER_STAGE(DS, Domain, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
INIT_SHADER_STAGE(GS, Geometry, VK_SHADER_STAGE_GEOMETRY_BIT);
|
||||
#endif
|
||||
INIT_SHADER_STAGE(PS, Pixel, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
#undef INIT_SHADER_STAGE
|
||||
_desc.pStages = _shaderStages;
|
||||
@@ -274,10 +280,13 @@ bool GPUPipelineStateVulkan::Init(const Description& desc)
|
||||
_descInputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
break;
|
||||
}
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
if (desc.HS)
|
||||
_descInputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
|
||||
#endif
|
||||
_desc.pInputAssemblyState = &_descInputAssembly;
|
||||
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
// Tessellation
|
||||
if (desc.HS)
|
||||
{
|
||||
@@ -285,6 +294,7 @@ bool GPUPipelineStateVulkan::Init(const Description& desc)
|
||||
_descTessellation.patchControlPoints = desc.HS->GetControlPointsCount();
|
||||
_desc.pTessellationState = &_descTessellation;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Viewport
|
||||
RenderToolsVulkan::ZeroStruct(_descViewport, VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO);
|
||||
|
||||
@@ -93,7 +93,9 @@ private:
|
||||
VkGraphicsPipelineCreateInfo _desc;
|
||||
VkPipelineShaderStageCreateInfo _shaderStages[ShaderStage_Count - 1];
|
||||
VkPipelineInputAssemblyStateCreateInfo _descInputAssembly;
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
VkPipelineTessellationStateCreateInfo _descTessellation;
|
||||
#endif
|
||||
VkPipelineViewportStateCreateInfo _descViewport;
|
||||
VkPipelineDynamicStateCreateInfo _descDynamic;
|
||||
VkDynamicState _dynamicStates[3];
|
||||
|
||||
@@ -107,6 +107,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
/// <summary>
|
||||
/// Hull Shader for Vulkan backend.
|
||||
/// </summary>
|
||||
@@ -146,7 +147,9 @@ public:
|
||||
{
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
/// <summary>
|
||||
/// Geometry Shader for Vulkan backend.
|
||||
/// </summary>
|
||||
@@ -165,6 +168,7 @@ public:
|
||||
{
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Pixel Shader for Vulkan backend.
|
||||
|
||||
@@ -194,6 +194,7 @@ GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, cons
|
||||
|
||||
break;
|
||||
}
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
case ShaderStage::Hull:
|
||||
{
|
||||
int32 controlPointsCount;
|
||||
@@ -206,11 +207,21 @@ GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, cons
|
||||
shader = New<GPUShaderProgramDSVulkan>(_device, initializer, header->DescriptorInfo, shaderModule);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
case ShaderStage::Hull:
|
||||
{
|
||||
int32 controlPointsCount;
|
||||
stream.ReadInt32(&controlPointsCount);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
case ShaderStage::Geometry:
|
||||
{
|
||||
shader = New<GPUShaderProgramGSVulkan>(_device, initializer, header->DescriptorInfo, shaderModule);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case ShaderStage::Pixel:
|
||||
{
|
||||
shader = New<GPUShaderProgramPSVulkan>(_device, initializer, header->DescriptorInfo, shaderModule);
|
||||
|
||||
@@ -104,6 +104,15 @@ Vector3 NavCrowd::GetAgentPosition(int32 id) const
|
||||
return result;
|
||||
}
|
||||
|
||||
void NavCrowd::SetAgentPosition(int32 id, const Vector3& position)
|
||||
{
|
||||
dtCrowdAgent* agent = _crowd->getEditableAgent(id);
|
||||
if (agent)
|
||||
{
|
||||
*(Float3*)agent->npos = Float3(position);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 NavCrowd::GetAgentVelocity(int32 id) const
|
||||
{
|
||||
Vector3 result = Vector3::Zero;
|
||||
@@ -115,6 +124,15 @@ Vector3 NavCrowd::GetAgentVelocity(int32 id) const
|
||||
return result;
|
||||
}
|
||||
|
||||
void NavCrowd::SetAgentVelocity(int32 id, const Vector3& velocity)
|
||||
{
|
||||
dtCrowdAgent* agent = _crowd->getEditableAgent(id);
|
||||
if (agent)
|
||||
{
|
||||
*(Float3*)agent->vel = Float3(velocity);
|
||||
}
|
||||
}
|
||||
|
||||
void NavCrowd::SetAgentProperties(int32 id, const NavAgentProperties& properties)
|
||||
{
|
||||
dtCrowdAgentParams agentParams;
|
||||
|
||||
@@ -63,6 +63,13 @@ public:
|
||||
/// <returns>The agent current position.</returns>
|
||||
API_FUNCTION() Vector3 GetAgentPosition(int32 id) const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the agent current position.
|
||||
/// </summary>
|
||||
/// <param name="id">The agent ID.</param>
|
||||
/// <param name="position">The agent position.</param>
|
||||
API_FUNCTION() void SetAgentPosition(int32 id, const Vector3& position);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the agent current velocity (direction * speed).
|
||||
/// </summary>
|
||||
@@ -70,6 +77,13 @@ public:
|
||||
/// <returns>The agent current velocity (direction * speed).</returns>
|
||||
API_FUNCTION() Vector3 GetAgentVelocity(int32 id) const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the agent current velocity (direction * speed).
|
||||
/// </summary>
|
||||
/// <param name="id">The agent ID.</param>
|
||||
/// <param name="velocity">The agent velocity (direction * speed).</param>
|
||||
API_FUNCTION() void SetAgentVelocity(int32 id, const Vector3& velocity);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the agent properties.
|
||||
/// </summary>
|
||||
|
||||
@@ -80,7 +80,16 @@ bool NetworkReplicationNode::DirtyObject(ScriptingObject* obj)
|
||||
if (index != -1)
|
||||
{
|
||||
NetworkReplicationHierarchyObject& e = Objects[index];
|
||||
e.ReplicationUpdatesLeft = 0;
|
||||
if (e.ReplicationFPS < -ZeroTolerance) // < 0
|
||||
{
|
||||
// Indicate for manual sync (see logic in Update)
|
||||
e.ReplicationUpdatesLeft = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Replicate it next frame
|
||||
e.ReplicationUpdatesLeft = 0;
|
||||
}
|
||||
}
|
||||
return index != -1;
|
||||
}
|
||||
@@ -93,6 +102,12 @@ void NetworkReplicationNode::Update(NetworkReplicationHierarchyUpdateResult* res
|
||||
{
|
||||
if (obj.ReplicationFPS < -ZeroTolerance) // < 0
|
||||
{
|
||||
if (obj.ReplicationUpdatesLeft)
|
||||
{
|
||||
// Marked as dirty to sync manually
|
||||
obj.ReplicationUpdatesLeft = 0;
|
||||
result->AddObject(obj.Object);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (obj.ReplicationFPS < ZeroTolerance) // == 0
|
||||
@@ -167,7 +182,7 @@ void NetworkReplicationGridNode::AddObject(NetworkReplicationHierarchyObject obj
|
||||
cell->MinCullDistance = obj.CullDistance;
|
||||
}
|
||||
cell->Node->AddObject(obj);
|
||||
_objectToCell[obj.Object] = coord;
|
||||
_objectToCell[obj.Object.Get()] = coord;
|
||||
|
||||
// Cache minimum culling distance for a whole cell to skip it at once
|
||||
cell->MinCullDistance = Math::Min(cell->MinCullDistance, obj.CullDistance);
|
||||
@@ -176,12 +191,10 @@ void NetworkReplicationGridNode::AddObject(NetworkReplicationHierarchyObject obj
|
||||
bool NetworkReplicationGridNode::RemoveObject(ScriptingObject* obj)
|
||||
{
|
||||
Int3 coord;
|
||||
|
||||
if (!_objectToCell.TryGet(obj, coord))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_children[coord].Node->RemoveObject(obj))
|
||||
{
|
||||
_objectToCell.Remove(obj);
|
||||
@@ -195,12 +208,10 @@ bool NetworkReplicationGridNode::RemoveObject(ScriptingObject* obj)
|
||||
bool NetworkReplicationGridNode::GetObject(ScriptingObject* obj, NetworkReplicationHierarchyObject& result)
|
||||
{
|
||||
Int3 coord;
|
||||
|
||||
if (!_objectToCell.TryGet(obj, coord))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_children[coord].Node->GetObject(obj, result))
|
||||
{
|
||||
return true;
|
||||
@@ -208,6 +219,16 @@ bool NetworkReplicationGridNode::GetObject(ScriptingObject* obj, NetworkReplicat
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetworkReplicationGridNode::DirtyObject(ScriptingObject* obj)
|
||||
{
|
||||
Int3 coord;
|
||||
if (_objectToCell.TryGet(obj, coord))
|
||||
{
|
||||
return _children[coord].Node->DirtyObject(obj);
|
||||
}
|
||||
return NetworkReplicationNode::DirtyObject(obj);
|
||||
}
|
||||
|
||||
void NetworkReplicationGridNode::Update(NetworkReplicationHierarchyUpdateResult* result)
|
||||
{
|
||||
CHECK(result);
|
||||
|
||||
@@ -20,11 +20,11 @@ API_STRUCT(NoDefault, Namespace = "FlaxEngine.Networking") struct FLAXENGINE_API
|
||||
|
||||
// The object to replicate.
|
||||
API_FIELD() ScriptingObjectReference<ScriptingObject> Object;
|
||||
// The target amount of the replication updates per second (frequency of the replication). Constrained by NetworkManager::NetworkFPS. Use 0 for 'always relevant' object and less than 0 (eg. -1) for 'never relevant' objects that would only get synched on client join once.
|
||||
// The target amount of the replication updates per second (frequency of the replication). Constrained by NetworkManager::NetworkFPS. Use 0 for 'always relevant' object and less than 0 (eg. -1) for 'never relevant' objects that would only get synced on client join once (or upon DirtyObject).
|
||||
API_FIELD() float ReplicationFPS = 60;
|
||||
// The minimum distance from the player to the object at which it can process replication. For example, players further away won't receive object data. Use 0 if unused.
|
||||
API_FIELD() float CullDistance = 15000;
|
||||
// Runtime value for update frames left for the next replication of this object. Matches NetworkManager::NetworkFPS calculated from ReplicationFPS.
|
||||
// Runtime value for update frames left for the next replication of this object. Matches NetworkManager::NetworkFPS calculated from ReplicationFPS. Set to 1 if ReplicationFPS less than 0 to indicate dirty object.
|
||||
API_FIELD(Attributes="HideInEditor") uint16 ReplicationUpdatesLeft = 0;
|
||||
|
||||
FORCE_INLINE NetworkReplicationHierarchyObject(const ScriptingObjectReference<ScriptingObject>& obj)
|
||||
@@ -257,6 +257,7 @@ public:
|
||||
void AddObject(NetworkReplicationHierarchyObject obj) override;
|
||||
bool RemoveObject(ScriptingObject* obj) override;
|
||||
bool GetObject(ScriptingObject* obj, NetworkReplicationHierarchyObject& result) override;
|
||||
bool DirtyObject(ScriptingObject* obj) override;
|
||||
void Update(NetworkReplicationHierarchyUpdateResult* result) override;
|
||||
};
|
||||
|
||||
|
||||
@@ -1203,7 +1203,7 @@ void NetworkReplicator::RemoveObject(ScriptingObject* obj)
|
||||
return;
|
||||
ScopeLock lock(ObjectsLock);
|
||||
const auto it = Objects.Find(obj->GetID());
|
||||
if (it != Objects.End())
|
||||
if (it == Objects.End())
|
||||
return;
|
||||
|
||||
// Remove object from the list
|
||||
|
||||
@@ -35,4 +35,7 @@
|
||||
|
||||
#define USE_MONO_AOT_MODE MONO_AOT_MODE_NONE
|
||||
|
||||
#define GPU_ALLOW_TESSELLATION_SHADERS 0 // Tess on mobile is not well supported
|
||||
#define GPU_ALLOW_GEOMETRY_SHADERS 0 // Don't even try GS on mobile
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2253,6 +2253,9 @@ bool LinuxPlatform::Init()
|
||||
}
|
||||
}
|
||||
|
||||
//Patch in numpad enter to normal enter, just like on windows.
|
||||
KeyCodeMap[104] = KeyboardKeys::Return;
|
||||
|
||||
Input::Mouse = Impl::Mouse = New<LinuxMouse>();
|
||||
Input::Keyboard = Impl::Keyboard = New<LinuxKeyboard>();
|
||||
LinuxInput::Init();
|
||||
|
||||
@@ -22,4 +22,7 @@
|
||||
#define PLATFORM_HAS_HEADLESS_MODE 1
|
||||
#define PLATFORM_DEBUG_BREAK __builtin_trap()
|
||||
|
||||
// MoltenVK has artifacts when using tess so disable it
|
||||
#define GPU_ALLOW_TESSELLATION_SHADERS 0
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,12 +16,12 @@ class FLAXENGINE_API Win32FileSystem : public FileSystemBase
|
||||
public:
|
||||
|
||||
// Creates a new directory
|
||||
// @param path Drectory path
|
||||
// @param path Directory path
|
||||
// @returns True if cannot create directory, otherwise false
|
||||
static bool CreateDirectory(const StringView& path);
|
||||
|
||||
// Deletes an existing directory
|
||||
// @param path Drectory path
|
||||
// @param path Directory path
|
||||
// @param deleteSubdirectories True if delete all subdirectories and files, otherwise false
|
||||
// @returns True if cannot delete directory, otherwise false
|
||||
static bool DeleteDirectory(const String& path, bool deleteContents = true);
|
||||
@@ -32,15 +32,15 @@ public:
|
||||
static bool DirectoryExists(const StringView& path);
|
||||
|
||||
// Finds the names of files (including their paths) that match the specified search pattern in the specified directory, using a value to determine whether to search subdirectories
|
||||
// @param results When this metod completes, this list contains list of all filenames that match the specified search pattern
|
||||
// @param results When this method completes, this list contains list of all filenames that match the specified search pattern
|
||||
// @param path Path of the directory to search in it
|
||||
// @param searchPattern Custo msearch pattern to use during that operation
|
||||
// @param option Addidtional search options
|
||||
// @param searchPattern Custom search pattern to use during that operation
|
||||
// @param option Additional search options
|
||||
// @returns True if an error occurred, otherwise false
|
||||
static bool DirectoryGetFiles(Array<String, HeapAllocation>& results, const String& path, const Char* searchPattern, DirectorySearchOption option = DirectorySearchOption::AllDirectories);
|
||||
|
||||
// Finds the names of directories (including their paths) that are inside the specified directory
|
||||
// @param results When this metod completes, this list contains list of all filenames that match the specified search pattern
|
||||
// @param results When this method completes, this list contains list of all filenames that match the specified search pattern
|
||||
// @param directory Path of the directory to search in it
|
||||
// @returns True if an error occurred, otherwise false
|
||||
static bool GetChildDirectories(Array<String, HeapAllocation>& results, const String& directory);
|
||||
|
||||
@@ -18,4 +18,7 @@
|
||||
#define USE_MONO_AOT 1
|
||||
#define USE_MONO_AOT_MODE MONO_AOT_MODE_FULL
|
||||
|
||||
#define GPU_ALLOW_TESSELLATION_SHADERS 0 // MoltenVK has artifacts when using tess so disable it
|
||||
#define GPU_ALLOW_GEOMETRY_SHADERS 0 // Don't even try GS on mobile
|
||||
|
||||
#endif
|
||||
|
||||
@@ -52,7 +52,9 @@ bool ColorGradingPass::Init()
|
||||
{
|
||||
// Detect if can use volume texture (3d) for a LUT (faster, requires geometry shader)
|
||||
const auto device = GPUDevice::Instance;
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
_useVolumeTexture = device->Limits.HasGeometryShaders && device->Limits.HasVolumeTextureRendering;
|
||||
#endif
|
||||
|
||||
// Pick a proper LUT pixels format
|
||||
_lutFormat = PixelFormat::R10G10B10A2_UNorm;
|
||||
@@ -85,7 +87,7 @@ bool ColorGradingPass::Init()
|
||||
bool ColorGradingPass::setupResources()
|
||||
{
|
||||
// Wait for shader
|
||||
if (!_shader->IsLoaded())
|
||||
if (!_shader || !_shader->IsLoaded())
|
||||
return true;
|
||||
const auto shader = _shader->GetShader();
|
||||
|
||||
@@ -101,6 +103,7 @@ bool ColorGradingPass::setupResources()
|
||||
if (!_psLut.IsValid())
|
||||
{
|
||||
StringAnsiView psName;
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
if (_useVolumeTexture)
|
||||
{
|
||||
psDesc.VS = shader->GetVS("VS_WriteToSlice");
|
||||
@@ -108,6 +111,7 @@ bool ColorGradingPass::setupResources()
|
||||
psName = "PS_Lut3D";
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
psName = "PS_Lut2D";
|
||||
}
|
||||
@@ -139,11 +143,13 @@ GPUTexture* ColorGradingPass::RenderLUT(RenderContext& renderContext)
|
||||
// For a 3D texture, the viewport is 16x16 (per slice), for a 2D texture, it's unwrapped to 256x16
|
||||
const int32 LutSize = 32; // this must match value in shader (see ColorGrading.shader and PostProcessing.shader)
|
||||
GPUTextureDescription lutDesc;
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
if (_useVolumeTexture)
|
||||
{
|
||||
lutDesc = GPUTextureDescription::New3D(LutSize, LutSize, LutSize, 1, _lutFormat);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
lutDesc = GPUTextureDescription::New2D(LutSize * LutSize, LutSize, 1, _lutFormat);
|
||||
}
|
||||
@@ -192,6 +198,7 @@ GPUTexture* ColorGradingPass::RenderLUT(RenderContext& renderContext)
|
||||
context->BindSR(0, useLut ? colorGrading.LutTexture->GetTexture() : nullptr);
|
||||
|
||||
// Draw
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
if (_useVolumeTexture)
|
||||
{
|
||||
context->SetRenderTarget(lut->ViewVolume());
|
||||
@@ -201,6 +208,7 @@ GPUTexture* ColorGradingPass::RenderLUT(RenderContext& renderContext)
|
||||
context->DrawFullscreenTriangle(numInstances);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
context->SetRenderTarget(lut->View());
|
||||
context->DrawFullscreenTriangle();
|
||||
|
||||
@@ -63,12 +63,14 @@ bool DepthOfFieldPass::Init()
|
||||
{
|
||||
_psDofDepthBlurGeneration = GPUDevice::Instance->CreatePipelineState();
|
||||
_psDoNotGenerateBokeh = GPUDevice::Instance->CreatePipelineState();
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
if (_platformSupportsBokeh)
|
||||
{
|
||||
_psBokehGeneration = GPUDevice::Instance->CreatePipelineState();
|
||||
_psBokeh = GPUDevice::Instance->CreatePipelineState();
|
||||
_psBokehComposite = GPUDevice::Instance->CreatePipelineState();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Load shaders
|
||||
@@ -137,6 +139,7 @@ bool DepthOfFieldPass::setupResources()
|
||||
if (_psDoNotGenerateBokeh->Init(psDesc))
|
||||
return true;
|
||||
}
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
if (_platformSupportsBokeh)
|
||||
{
|
||||
if (!_psBokehGeneration->IsValid())
|
||||
@@ -171,6 +174,7 @@ bool DepthOfFieldPass::setupResources()
|
||||
if (_bokehIndirectArgsBuffer->Init(GPUBufferDescription::Argument(&indirectArgsBufferInitData, sizeof(indirectArgsBufferInitData))))
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -296,6 +300,7 @@ void DepthOfFieldPass::Render(RenderContext& renderContext, GPUTexture*& frame,
|
||||
auto dofFormat = renderContext.Buffers->GetOutputFormat();
|
||||
tempDesc = GPUTextureDescription::New2D(dofWidth, dofHeight, dofFormat);
|
||||
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
// Do the bokeh point generation, or just do a copy if disabled
|
||||
bool isBokehGenerationEnabled = dofSettings.BokehEnabled && _platformSupportsBokeh && dofSettings.BokehBrightness > 0.0f && dofSettings.BokehSize > 0.0f;
|
||||
if (isBokehGenerationEnabled)
|
||||
@@ -329,6 +334,7 @@ void DepthOfFieldPass::Render(RenderContext& renderContext, GPUTexture*& frame,
|
||||
context->DrawFullscreenTriangle();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Generate bokeh points
|
||||
context->BindSR(0, frame);
|
||||
@@ -380,6 +386,7 @@ void DepthOfFieldPass::Render(RenderContext& renderContext, GPUTexture*& frame,
|
||||
context->ResetSR();
|
||||
}
|
||||
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
// Render the bokeh points
|
||||
if (isBokehGenerationEnabled)
|
||||
{
|
||||
@@ -418,6 +425,7 @@ void DepthOfFieldPass::Render(RenderContext& renderContext, GPUTexture*& frame,
|
||||
RenderTargetPool::Release(bokehTarget);
|
||||
Swap(frame, tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
RenderTargetPool::Release(depthBlurTarget);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ void EyeAdaptationPass::Render(RenderContext& renderContext, GPUTexture* colorBu
|
||||
renderContext.Buffers->LastEyeAdaptationTime = 0.0f;
|
||||
if ((view.Flags & ViewFlags::EyeAdaptation) == ViewFlags::None || settings.Mode == EyeAdaptationMode::None || checkIfSkipPass())
|
||||
return;
|
||||
|
||||
PROFILE_GPU_CPU("Eye Adaptation");
|
||||
|
||||
// Setup constants
|
||||
@@ -218,14 +217,15 @@ String EyeAdaptationPass::ToString() const
|
||||
|
||||
bool EyeAdaptationPass::Init()
|
||||
{
|
||||
_canUseHistogram = GPUDevice::Instance->Limits.HasCompute;
|
||||
auto device = GPUDevice::Instance;
|
||||
_canUseHistogram = device->Limits.HasCompute;
|
||||
|
||||
// Create pipeline states
|
||||
_psManual = GPUDevice::Instance->CreatePipelineState();
|
||||
_psLuminanceMap = GPUDevice::Instance->CreatePipelineState();
|
||||
_psBlendLuminance = GPUDevice::Instance->CreatePipelineState();
|
||||
_psApplyLuminance = GPUDevice::Instance->CreatePipelineState();
|
||||
_psHistogram = GPUDevice::Instance->CreatePipelineState();
|
||||
_psManual = device->CreatePipelineState();
|
||||
_psLuminanceMap = device->CreatePipelineState();
|
||||
_psBlendLuminance = device->CreatePipelineState();
|
||||
_psApplyLuminance = device->CreatePipelineState();
|
||||
_psHistogram = device->CreatePipelineState();
|
||||
|
||||
// Load shaders
|
||||
_shader = Content::LoadAsyncInternal<Shader>(TEXT("Shaders/EyeAdaptation"));
|
||||
|
||||
@@ -29,7 +29,6 @@ GPUBuffer* HistogramPass::Render(RenderContext& renderContext, GPUTexture* color
|
||||
auto context = device->GetMainContext();
|
||||
if (checkIfSkipPass() || !_isSupported)
|
||||
return nullptr;
|
||||
|
||||
PROFILE_GPU_CPU("Histogram");
|
||||
|
||||
// Setup constants
|
||||
|
||||
@@ -59,7 +59,7 @@ int32 TexturesStreamingHandler::CalculateResidency(StreamableResource* resource,
|
||||
|
||||
if (mipLevels > 0 && mipLevels < texture._minMipCountBlockCompressed && texture._isBlockCompressed)
|
||||
{
|
||||
// Block compressed textures require minimum size of 4
|
||||
// Block compressed textures require minimum size of block size (eg. 4 for BC formats)
|
||||
mipLevels = texture._minMipCountBlockCompressed;
|
||||
}
|
||||
|
||||
|
||||
@@ -421,15 +421,31 @@ void MaterialGenerator::ProcessGroupMaterial(Box* box, Node* node, Value& value)
|
||||
// DDX
|
||||
case 30:
|
||||
{
|
||||
const auto inValue = tryGetValue(node->GetBox(0), 0, Value::Zero);
|
||||
value = writeLocal(inValue.Type, String::Format(TEXT("ddx({0})"), inValue.Value), node);
|
||||
if (_treeType == MaterialTreeType::PixelShader)
|
||||
{
|
||||
const auto inValue = tryGetValue(node->GetBox(0), 0, Value::Zero);
|
||||
value = writeLocal(inValue.Type, String::Format(TEXT("ddx({0})"), inValue.Value), node);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No derivatives support in VS/DS
|
||||
value = Value::Zero;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// DDY
|
||||
case 31:
|
||||
{
|
||||
const auto inValue = tryGetValue(node->GetBox(0), 0, Value::Zero);
|
||||
value = writeLocal(inValue.Type, String::Format(TEXT("ddy({0})"), inValue.Value), node);
|
||||
if (_treeType == MaterialTreeType::PixelShader)
|
||||
{
|
||||
const auto inValue = tryGetValue(node->GetBox(0), 0, Value::Zero);
|
||||
value = writeLocal(inValue.Type, String::Format(TEXT("ddy({0})"), inValue.Value), node);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No derivatives support in VS/DS
|
||||
value = Value::Zero;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Sign
|
||||
|
||||
@@ -196,7 +196,7 @@ public:
|
||||
String CollisionMeshesPrefix = TEXT("");
|
||||
// The type of collision that should be generated if the mesh has a collision prefix specified.
|
||||
API_FIELD(Attributes = "EditorOrder(105), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowGeometry))")
|
||||
CollisionDataType CollisionType = CollisionDataType::TriangleMesh;
|
||||
CollisionDataType CollisionType = CollisionDataType::ConvexMesh;
|
||||
|
||||
public: // Transform
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ namespace FlaxEngine
|
||||
if (renderContext.View.Frustum.Contains(bounds.GetBoundingBox()) == ContainmentType.Disjoint)
|
||||
return;
|
||||
|
||||
Profiler.BeginEvent("UI Canvas");
|
||||
Profiler.BeginEventGPU("UI Canvas");
|
||||
|
||||
// Calculate rendering matrix (world*view*projection)
|
||||
@@ -90,6 +91,7 @@ namespace FlaxEngine
|
||||
Render2D.CallDrawing(Canvas.GUI, context, input, depthBuffer, ref viewProjectionMatrix);
|
||||
Render2D.Features = features;
|
||||
|
||||
Profiler.EndEvent();
|
||||
Profiler.EndEventGPU();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user