Skip to content

Commit

Permalink
Refactored render system information query.
Browse files Browse the repository at this point in the history
- Deprecated protected member functions RenderSystem::SetRendererInfo() and RenderSystem::SetRenderingCaps() in the place of RenderSystem::QueryRendererDetails().
- GL backend can finally query renderer information before any resource has been created.
- Introduced small breaking change as GetRendererInfo() and GetRenderingCaps() are no longer constant member functions;
  This was necessary to allow the backend to query the information on demand and cache it so that the GL backend can ensure a GL context is present.
  • Loading branch information
LukasBanana committed Jul 4, 2024
1 parent fe9dd61 commit 356207f
Show file tree
Hide file tree
Showing 21 changed files with 409 additions and 290 deletions.
17 changes: 17 additions & 0 deletions include/LLGL/Backend/RenderSystem.Internal.inl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* RenderSystem.Internal.inl
*
* Copyright (c) 2015 Lukas Hermanns. All rights reserved.
* Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt).
*/

/* ----- Internal ------ */

virtual bool QueryRendererDetails(
LLGL::RendererInfo* outInfo,
LLGL::RenderingCapabilities* outCaps)
override final;



// ================================================================================
29 changes: 21 additions & 8 deletions include/LLGL/RenderSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,17 +192,17 @@ class LLGL_EXPORT RenderSystem : public Interface

/**
\brief Returns basic renderer information.
\remarks The validity of these information is only guaranteed if this function is called
after a valid swap-chain has been created. Otherwise the behavior is undefined!
\remarks This is not a constant member function because the first call will invoke the query,
while subsequent calls with return the cached information.
*/
const RendererInfo& GetRendererInfo() const;
const RendererInfo& GetRendererInfo();

/**
\brief Returns the rendering capabilities.
\remarks The validity of these information is only guaranteed if this function is called
after a valid swap-chain has been created. Otherwise the behavior is undefined!
\remarks This is not a constant member function because the first call will invoke the query,
while subsequent calls with return the cached information.
*/
const RenderingCapabilities& GetRenderingCaps() const;
const RenderingCapabilities& GetRenderingCaps();

/**
\brief Returns a pointer to the report or null if there is none.
Expand Down Expand Up @@ -641,12 +641,25 @@ class LLGL_EXPORT RenderSystem : public Interface
*/
void Errorf(const char* format, ...);

//! Sets the renderer information.
//! \deprecated Since 0.04b; Implement QueryRendererDetails() instead!
LLGL_DEPRECATED("RenderSystem::SetRendererInfo is deprecated since 0.04b; Implement QueryRendererDetails() instead!")
void SetRendererInfo(const RendererInfo& info);

//! Sets the rendering capabilities.
//! \deprecated Since 0.04b; Implement QueryRendererDetails() instead!
LLGL_DEPRECATED("RenderSystem::SetRendererInfo is deprecated since 0.04b; Implement QueryRendererDetails() instead!")
void SetRenderingCaps(const RenderingCapabilities& caps);

protected:

/**
\brief Queries the renderer information and capacilities.
\param[out] outInfo Specifies the output parameter for the renderer info. This may be null.
\param[out] outCaps Specifies the output parameter for the renderer capabilities. This may be null.
\remarks This function may be called separately for both the information and capabilities query.
\return True on success. Otherwise, the backend is not reasy yet to provide the requested details.
*/
virtual bool QueryRendererDetails(RendererInfo* outInfo, RenderingCapabilities* outCaps) = 0;

protected:

//! Validates the specified buffer descriptor to be used for buffer creation.
Expand Down
47 changes: 21 additions & 26 deletions sources/Renderer/DebugLayer/DbgRenderSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,13 @@ All the actual render system objects are stored in the members named "instance",
*/

DbgRenderSystem::DbgRenderSystem(RenderSystemPtr&& instance, RenderingDebugger* debugger) :
instance_ { std::forward<RenderSystemPtr&&>(instance) },
debugger_ { debugger },
caps_ { GetRenderingCaps() },
features_ { caps_.features },
limits_ { caps_.limits }
instance_ { std::forward<RenderSystemPtr&&>(instance) },
debugger_ { debugger },
caps_ { GetRenderingCaps() },
features_ { caps_.features },
limits_ { caps_.limits },
commandQueue_ { MakeUnique<DbgCommandQueue>(*(instance_->GetCommandQueue()), profile_, debugger_) }
{
/* Initialize rendering capabilities from wrapped instance */
UpdateRenderingCaps();
}

void DbgRenderSystem::FlushProfile()
Expand All @@ -55,18 +54,12 @@ void DbgRenderSystem::FlushProfile()

SwapChain* DbgRenderSystem::CreateSwapChain(const SwapChainDescriptor& swapChainDesc, const std::shared_ptr<Surface>& surface)
{
/* Create primary swap-chain */
auto* swapChainInstance = instance_->CreateSwapChain(swapChainDesc, surface);

/* Instantiate command queue if not done and update rendering capabilities from wrapped instance */
if (!commandQueue_)
{
UpdateRenderingCaps();
commandQueue_ = MakeUnique<DbgCommandQueue>(*(instance_->GetCommandQueue()), profile_, debugger_);
}

/* Flush frame profile on SwapChain::Present() calls */
return swapChains_.emplace<DbgSwapChain>(*swapChainInstance, swapChainDesc, std::bind(&DbgRenderSystem::FlushProfile, this));
/* Create swap-chain and flush frame profile on SwapChain::Present() calls */
return swapChains_.emplace<DbgSwapChain>(
*instance_->CreateSwapChain(swapChainDesc, surface),
swapChainDesc,
std::bind(&DbgRenderSystem::FlushProfile, this)
);
}

void DbgRenderSystem::Release(SwapChain& swapChain)
Expand Down Expand Up @@ -602,6 +595,15 @@ bool DbgRenderSystem::GetNativeHandle(void* nativeHandle, std::size_t nativeHand
* ======= Private: =======
*/

bool DbgRenderSystem::QueryRendererDetails(RendererInfo* outInfo, RenderingCapabilities* outCaps)
{
if (outInfo != nullptr)
*outInfo = instance_->GetRendererInfo();
if (outCaps != nullptr)
*outCaps = instance_->GetRenderingCaps();
return true;
}

void DbgRenderSystem::ValidateBindFlags(long flags)
{
constexpr long bufferOnlyFlags =
Expand Down Expand Up @@ -2170,13 +2172,6 @@ void DbgRenderSystem::ReleaseDbg(HWObjectContainer<T>& cont, TBase& entry)
cont.erase(&entry);
}

void DbgRenderSystem::UpdateRenderingCaps()
{
/* Store meta data about render system */
SetRendererInfo(instance_->GetRendererInfo());
SetRenderingCaps(instance_->GetRenderingCaps());
}


} // /namespace LLGL

Expand Down
6 changes: 4 additions & 2 deletions sources/Renderer/DebugLayer/DbgRenderSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ class DbgRenderSystem final : public RenderSystem

void FlushProfile();

private:

#include <LLGL/Backend/RenderSystem.Internal.inl>

private:

void ValidateBindFlags(long flags);
Expand Down Expand Up @@ -114,8 +118,6 @@ class DbgRenderSystem final : public RenderSystem

std::vector<ResourceViewDescriptor> GetResourceViewInstanceCopy(const ArrayView<ResourceViewDescriptor>& resourceViews);

void UpdateRenderingCaps();

private:

/* ----- Common objects ----- */
Expand Down
175 changes: 91 additions & 84 deletions sources/Renderer/Direct3D11/D3D11RenderSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ D3D11RenderSystem::D3D11RenderSystem(const RenderSystemDescriptor& renderSystemD

/* Initialize states and renderer information */
CreateStateManagerAndCommandQueue();
QueryRendererInfo();
QueryRenderingCaps();

/* Initialize MIP-map generator singleton */
D3D11MipGenerator::Get().InitializeDevice(device_);
Expand Down Expand Up @@ -551,6 +549,15 @@ void D3D11RenderSystem::ClearStateForAllContexts()
* ======= Private: =======
*/

bool D3D11RenderSystem::QueryRendererDetails(RendererInfo* outInfo, RenderingCapabilities* outCaps)
{
if (outInfo != nullptr)
QueryRendererInfo(*outInfo);
if (outCaps != nullptr)
QueryRenderingCaps(*outCaps);
return true;
}

void D3D11RenderSystem::CreateFactory()
{
/* Create DXGI factory */
Expand Down Expand Up @@ -740,18 +747,24 @@ static const char* DXFeatureLevelToShaderModel(D3D_FEATURE_LEVEL featureLevel)
return "";
}

void D3D11RenderSystem::QueryRendererInfo()
void D3D11RenderSystem::QueryRendererInfo(RendererInfo& info)
{
RendererInfo info;

/* Initialize Direct3D version string */
const int minorVersion = GetMinorVersion();
switch (minorVersion)
{
case 3: info.rendererName = "Direct3D 11.3"; break;
case 2: info.rendererName = "Direct3D 11.2"; break;
case 1: info.rendererName = "Direct3D 11.1"; break;
default: info.rendererName = "Direct3D 11.0"; break;
case 3:
info.rendererName = "Direct3D 11.3";
break;
case 2:
info.rendererName = "Direct3D 11.2";
break;
case 1:
info.rendererName = "Direct3D 11.1";
break;
default:
info.rendererName = "Direct3D 11.0";
break;
}

/* Initialize HLSL version string */
Expand All @@ -760,8 +773,6 @@ void D3D11RenderSystem::QueryRendererInfo()
/* Initialize video adapter strings */
info.deviceName = videoAdatperInfo_.name.c_str();
info.vendorName = GetVendorName(videoAdatperInfo_.vendor);

SetRendererInfo(info);
}

// Returns the HLSL version for the specified Direct3D feature level.
Expand Down Expand Up @@ -828,80 +839,76 @@ static std::uint32_t GetMaxRenderTargets(D3D_FEATURE_LEVEL featureLevel)
}

// see https://msdn.microsoft.com/en-us/library/windows/desktop/ff476876(v=vs.85).aspx
void D3D11RenderSystem::QueryRenderingCaps()
void D3D11RenderSystem::QueryRenderingCaps(RenderingCapabilities& caps)
{
RenderingCapabilities caps;
{
const D3D_FEATURE_LEVEL featureLevel = GetFeatureLevel();
const int minorVersion = GetMinorVersion();

const std::uint32_t maxThreadGroups = 65535u;//D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;

/* Query common attributes */
caps.screenOrigin = ScreenOrigin::UpperLeft;
caps.clippingRange = ClippingRange::ZeroToOne;
caps.shadingLanguages = DXGetHLSLVersions(featureLevel);
caps.textureFormats = GetDefaultSupportedDXTextureFormats(featureLevel);

caps.features.hasRenderTargets = true;
caps.features.has3DTextures = true;
caps.features.hasCubeTextures = true;
caps.features.hasArrayTextures = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
caps.features.hasCubeArrayTextures = (featureLevel >= D3D_FEATURE_LEVEL_10_1);
caps.features.hasMultiSampleTextures = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
caps.features.hasMultiSampleArrayTextures = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
caps.features.hasTextureViews = true;
caps.features.hasTextureViewSwizzle = false; // not supported by D3D11
caps.features.hasBufferViews = true;
caps.features.hasConstantBuffers = true;
caps.features.hasStorageBuffers = true;
caps.features.hasGeometryShaders = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
caps.features.hasTessellationShaders = (featureLevel >= D3D_FEATURE_LEVEL_11_0);
caps.features.hasTessellatorStage = (featureLevel >= D3D_FEATURE_LEVEL_11_0);
caps.features.hasComputeShaders = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
caps.features.hasInstancing = (featureLevel >= D3D_FEATURE_LEVEL_9_3);
caps.features.hasOffsetInstancing = (featureLevel >= D3D_FEATURE_LEVEL_9_3);
caps.features.hasIndirectDrawing = (featureLevel >= D3D_FEATURE_LEVEL_10_0);//???
caps.features.hasViewportArrays = true;
caps.features.hasConservativeRasterization = (minorVersion >= 3);
caps.features.hasStreamOutputs = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
caps.features.hasLogicOp = (featureLevel >= D3D_FEATURE_LEVEL_11_1);
caps.features.hasPipelineStatistics = true;
caps.features.hasRenderCondition = true;

/* Query limits */
caps.limits.lineWidthRange[0] = 1.0f;
caps.limits.lineWidthRange[1] = 1.0f;
caps.limits.maxTextureArrayLayers = (featureLevel >= D3D_FEATURE_LEVEL_10_0 ? 2048u : 256u);
caps.limits.maxColorAttachments = GetMaxRenderTargets(featureLevel);
caps.limits.maxPatchVertices = 32u;
caps.limits.max1DTextureSize = GetMaxTextureDimension(featureLevel);
caps.limits.max2DTextureSize = GetMaxTextureDimension(featureLevel);
caps.limits.max3DTextureSize = (featureLevel >= D3D_FEATURE_LEVEL_10_0 ? 2048u : 256u);
caps.limits.maxCubeTextureSize = GetMaxCubeTextureDimension(featureLevel);
caps.limits.maxAnisotropy = (featureLevel >= D3D_FEATURE_LEVEL_9_2 ? 16u : 2u);
caps.limits.maxComputeShaderWorkGroups[0] = maxThreadGroups;
caps.limits.maxComputeShaderWorkGroups[1] = maxThreadGroups;
caps.limits.maxComputeShaderWorkGroups[2] = (featureLevel >= D3D_FEATURE_LEVEL_11_0 ? maxThreadGroups : 1u);
caps.limits.maxComputeShaderWorkGroupSize[0] = 1024u;
caps.limits.maxComputeShaderWorkGroupSize[1] = 1024u;
caps.limits.maxComputeShaderWorkGroupSize[2] = 1024u;
caps.limits.maxViewports = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
caps.limits.maxViewportSize[0] = D3D11_VIEWPORT_BOUNDS_MAX;
caps.limits.maxViewportSize[1] = D3D11_VIEWPORT_BOUNDS_MAX;
caps.limits.maxBufferSize = UINT_MAX;
caps.limits.maxConstantBufferSize = D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16;
caps.limits.maxStreamOutputs = 4u;
caps.limits.maxTessFactor = 64u;
caps.limits.minConstantBufferAlignment = 256u;
caps.limits.minSampledBufferAlignment = 32u;
caps.limits.minStorageBufferAlignment = 32u;
caps.limits.maxColorBufferSamples = FindSuitableSampleDesc(device_.Get(), DXGI_FORMAT_R8G8B8A8_UNORM).Count;
caps.limits.maxDepthBufferSamples = FindSuitableSampleDesc(device_.Get(), DXGI_FORMAT_D32_FLOAT).Count;
caps.limits.maxStencilBufferSamples = FindSuitableSampleDesc(device_.Get(), DXGI_FORMAT_D32_FLOAT_S8X24_UINT).Count;
caps.limits.maxNoAttachmentSamples = D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT;
}
SetRenderingCaps(caps);
const D3D_FEATURE_LEVEL featureLevel = GetFeatureLevel();
const int minorVersion = GetMinorVersion();

const std::uint32_t maxThreadGroups = 65535u;//D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;

/* Query common attributes */
caps.screenOrigin = ScreenOrigin::UpperLeft;
caps.clippingRange = ClippingRange::ZeroToOne;
caps.shadingLanguages = DXGetHLSLVersions(featureLevel);
caps.textureFormats = GetDefaultSupportedDXTextureFormats(featureLevel);

caps.features.hasRenderTargets = true;
caps.features.has3DTextures = true;
caps.features.hasCubeTextures = true;
caps.features.hasArrayTextures = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
caps.features.hasCubeArrayTextures = (featureLevel >= D3D_FEATURE_LEVEL_10_1);
caps.features.hasMultiSampleTextures = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
caps.features.hasMultiSampleArrayTextures = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
caps.features.hasTextureViews = true;
caps.features.hasTextureViewSwizzle = false; // not supported by D3D11
caps.features.hasBufferViews = true;
caps.features.hasConstantBuffers = true;
caps.features.hasStorageBuffers = true;
caps.features.hasGeometryShaders = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
caps.features.hasTessellationShaders = (featureLevel >= D3D_FEATURE_LEVEL_11_0);
caps.features.hasTessellatorStage = (featureLevel >= D3D_FEATURE_LEVEL_11_0);
caps.features.hasComputeShaders = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
caps.features.hasInstancing = (featureLevel >= D3D_FEATURE_LEVEL_9_3);
caps.features.hasOffsetInstancing = (featureLevel >= D3D_FEATURE_LEVEL_9_3);
caps.features.hasIndirectDrawing = (featureLevel >= D3D_FEATURE_LEVEL_10_0);//???
caps.features.hasViewportArrays = true;
caps.features.hasConservativeRasterization = (minorVersion >= 3);
caps.features.hasStreamOutputs = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
caps.features.hasLogicOp = (featureLevel >= D3D_FEATURE_LEVEL_11_1);
caps.features.hasPipelineStatistics = true;
caps.features.hasRenderCondition = true;

/* Query limits */
caps.limits.lineWidthRange[0] = 1.0f;
caps.limits.lineWidthRange[1] = 1.0f;
caps.limits.maxTextureArrayLayers = (featureLevel >= D3D_FEATURE_LEVEL_10_0 ? 2048u : 256u);
caps.limits.maxColorAttachments = GetMaxRenderTargets(featureLevel);
caps.limits.maxPatchVertices = 32u;
caps.limits.max1DTextureSize = GetMaxTextureDimension(featureLevel);
caps.limits.max2DTextureSize = GetMaxTextureDimension(featureLevel);
caps.limits.max3DTextureSize = (featureLevel >= D3D_FEATURE_LEVEL_10_0 ? 2048u : 256u);
caps.limits.maxCubeTextureSize = GetMaxCubeTextureDimension(featureLevel);
caps.limits.maxAnisotropy = (featureLevel >= D3D_FEATURE_LEVEL_9_2 ? 16u : 2u);
caps.limits.maxComputeShaderWorkGroups[0] = maxThreadGroups;
caps.limits.maxComputeShaderWorkGroups[1] = maxThreadGroups;
caps.limits.maxComputeShaderWorkGroups[2] = (featureLevel >= D3D_FEATURE_LEVEL_11_0 ? maxThreadGroups : 1u);
caps.limits.maxComputeShaderWorkGroupSize[0] = 1024u;
caps.limits.maxComputeShaderWorkGroupSize[1] = 1024u;
caps.limits.maxComputeShaderWorkGroupSize[2] = 1024u;
caps.limits.maxViewports = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
caps.limits.maxViewportSize[0] = D3D11_VIEWPORT_BOUNDS_MAX;
caps.limits.maxViewportSize[1] = D3D11_VIEWPORT_BOUNDS_MAX;
caps.limits.maxBufferSize = UINT_MAX;
caps.limits.maxConstantBufferSize = D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16;
caps.limits.maxStreamOutputs = 4u;
caps.limits.maxTessFactor = 64u;
caps.limits.minConstantBufferAlignment = 256u;
caps.limits.minSampledBufferAlignment = 32u;
caps.limits.minStorageBufferAlignment = 32u;
caps.limits.maxColorBufferSamples = FindSuitableSampleDesc(device_.Get(), DXGI_FORMAT_R8G8B8A8_UNORM).Count;
caps.limits.maxDepthBufferSamples = FindSuitableSampleDesc(device_.Get(), DXGI_FORMAT_D32_FLOAT).Count;
caps.limits.maxStencilBufferSamples = FindSuitableSampleDesc(device_.Get(), DXGI_FORMAT_D32_FLOAT_S8X24_UINT).Count;
caps.limits.maxNoAttachmentSamples = D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT;
}

int D3D11RenderSystem::GetMinorVersion() const
Expand Down
Loading

0 comments on commit 356207f

Please sign in to comment.