Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/modules/graphics/Graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,7 @@ void Graphics::restoreState(const DisplayState &s)

setStencilState(s.stencil);
setDepthMode(s.depthTest, s.depthWrite);
setDepthClamp(s.depthClampEnable);

setColorMask(s.colorMask);
setWireframe(s.wireframe);
Expand Down Expand Up @@ -926,6 +927,9 @@ void Graphics::restoreStateChecked(const DisplayState &s)
if (s.depthTest != cur.depthTest || s.depthWrite != cur.depthWrite)
setDepthMode(s.depthTest, s.depthWrite);

if(s.depthClampEnable != cur.depthClampEnable)
setDepthClamp(s.depthClampEnable);

if (s.colorMask != cur.colorMask)
setColorMask(s.colorMask);

Expand Down
8 changes: 8 additions & 0 deletions src/modules/graphics/Graphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ class Graphics : public Module
FEATURE_TEXEL_BUFFER,
FEATURE_COPY_TEXTURE_TO_BUFFER,
FEATURE_INDIRECT_DRAW,
FEATURE_DEPTH_CLAMP,
FEATURE_MAX_ENUM
};

Expand Down Expand Up @@ -621,6 +622,12 @@ class Graphics : public Module
void setDepthMode();
void getDepthMode(CompareMode &compare, bool &write) const;

/**
* Clamps the depth valies to [0, 1] range instead of clipping geomentry
* away at near and far planes
*/
virtual void setDepthClamp(bool enable) = 0;

void setMeshCullMode(CullMode cull);
CullMode getMeshCullMode() const;

Expand Down Expand Up @@ -948,6 +955,7 @@ class Graphics : public Module

CompareMode depthTest = COMPARE_ALWAYS;
bool depthWrite = false;
bool depthClampEnable = false;

CullMode meshCullMode = CULL_NONE;
Winding winding = WINDING_CCW;
Expand Down
2 changes: 2 additions & 0 deletions src/modules/graphics/metal/Graphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ class Graphics final : public love::graphics::Graphics

void setDepthMode(CompareMode compare, bool write) override;

void setDepthClamp(bool enable) override;

void setFrontFaceWinding(Winding winding) override;

void setColorMask(ColorChannelMask mask) override;
Expand Down
19 changes: 18 additions & 1 deletion src/modules/graphics/metal/Graphics.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,9 @@ static bool isClampOne(SamplerState::WrapMode w)
id<MTLDepthStencilState> mtlstate = getCachedDepthStencilState(depth, state.stencil);

[encoder setDepthStencilState:mtlstate];

// Also set the depth clamping (depth state change is tirggered for both deptstate and clamp state changes)
[encoder setDepthClipMode: state.depthClampEnable ? MTLDepthClipModeClamp : MTLDepthClipModeClip];
}

if (dirtyState & STATEBIT_STENCIL)
Expand Down Expand Up @@ -1842,6 +1845,18 @@ static inline void advanceVertexOffsets(const VertexAttributes &attributes, Buff
}
}

void Graphics::setDepthClamp(bool enable)
{
DisplayState &state = states.back();

if(state.depthClampEnable != enable)
{
flushBatchedDraws();
state.depthClampEnable = enable;
dirtyRenderState |= STATEBIT_DEPTH;
}
}

void Graphics::setFrontFaceWinding(Winding winding)
{
if (states.back().winding != winding)
Expand Down Expand Up @@ -2266,7 +2281,9 @@ static inline void advanceVertexOffsets(const VertexAttributes &attributes, Buff
else
capabilities.features[FEATURE_INDIRECT_DRAW] = false;

static_assert(FEATURE_MAX_ENUM == 13, "Graphics::initCapabilities must be updated when adding a new graphics feature!");
capabilities.features[FEATURE_DEPTH_CLAMP] = true;

static_assert(FEATURE_MAX_ENUM == 14, "Graphics::initCapabilities must be updated when adding a new graphics feature!");

// https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
capabilities.limits[LIMIT_POINT_SIZE] = 511;
Expand Down
37 changes: 36 additions & 1 deletion src/modules/graphics/opengl/Graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1453,6 +1453,19 @@ void Graphics::setDepthMode(CompareMode compare, bool write)
}
}

void Graphics::setDepthClamp(bool enable)
{
if(capabilities.features[FEATURE_DEPTH_CLAMP]) {
DisplayState &state = states.back();

if(state.depthClampEnable != enable)
flushBatchedDraws();

gl.setEnableState(OpenGL::ENABLE_DEPTH_CLAMP, enable);
state.depthClampEnable = enable;
}
}

void Graphics::setFrontFaceWinding(Winding winding)
{
DisplayState &state = states.back();
Expand Down Expand Up @@ -1609,7 +1622,12 @@ void Graphics::initCapabilities()
capabilities.features[FEATURE_TEXEL_BUFFER] = gl.isBufferUsageSupported(BUFFERUSAGE_TEXEL);
capabilities.features[FEATURE_COPY_TEXTURE_TO_BUFFER] = gl.isCopyTextureToBufferSupported();
capabilities.features[FEATURE_INDIRECT_DRAW] = capabilities.features[FEATURE_GLSL4];
static_assert(FEATURE_MAX_ENUM == 13, "Graphics::initCapabilities must be updated when adding a new graphics feature!");
capabilities.features[FEATURE_DEPTH_CLAMP] = hasExtension("GL_EXT_depth_clamp") ||
hasExtension("GL_NV_depth_clamp") ||
hasExtension("GL_AMD_depth_clamp_separate") ||
hasExtension("GL_ARB_depth_clamp") ||
GLAD_VERSION_3_2;
static_assert(FEATURE_MAX_ENUM == 14, "Graphics::initCapabilities must be updated when adding a new graphics feature!");

capabilities.limits[LIMIT_POINT_SIZE] = gl.getMaxPointSize();
capabilities.limits[LIMIT_TEXTURE_SIZE] = gl.getMax2DTextureSize();
Expand Down Expand Up @@ -1738,6 +1756,23 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage)
return (usage & pixelFormatUsage[format][readable ? 1 : 0]) == usage;
}

bool Graphics::hasExtension(const char* name)
{
GLint numExts = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &numExts);
for (GLint i = 0; i < numExts; ++i) {
const char* ext = (const char*)glGetStringi(GL_EXTENSIONS, i);
::printf("extension: %s \n", ext);
if (strcmp(ext, name) == 0) return true;
}
// fallback for older contexts
const char* all = (const char*)glGetString(GL_EXTENSIONS);
if (all) {
return strstr(all, name) != nullptr;
}
return false;
}

} // opengl
} // graphics
} // love
4 changes: 4 additions & 0 deletions src/modules/graphics/opengl/Graphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class Graphics final : public love::graphics::Graphics

void setDepthMode(CompareMode compare, bool write) override;

void setDepthClamp(bool enable) override;

void setFrontFaceWinding(Winding winding) override;

void setColorMask(ColorChannelMask mask) override;
Expand Down Expand Up @@ -144,6 +146,8 @@ class Graphics final : public love::graphics::Graphics
void setRenderTargetsInternal(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture) override;
void initCapabilities() override;
void getAPIStats(int &shaderswitches) const override;

bool hasExtension(const char* name);

void endPass(bool presenting);
GLuint bindCachedFBO(const RenderTargets &targets);
Expand Down
3 changes: 3 additions & 0 deletions src/modules/graphics/opengl/OpenGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,9 @@ void OpenGL::setEnableState(EnableState enablestate, bool enable)
case ENABLE_FRAMEBUFFER_SRGB:
glstate = GL_FRAMEBUFFER_SRGB;
break;
case ENABLE_DEPTH_CLAMP:
glstate = GL_DEPTH_CLAMP;
break;
case ENABLE_MAX_ENUM:
break;
}
Expand Down
1 change: 1 addition & 0 deletions src/modules/graphics/opengl/OpenGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class OpenGL
ENABLE_SCISSOR_TEST,
ENABLE_FACE_CULL,
ENABLE_FRAMEBUFFER_SRGB,
ENABLE_DEPTH_CLAMP,
ENABLE_MAX_ENUM
};

Expand Down
58 changes: 53 additions & 5 deletions src/modules/graphics/vulkan/Graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,18 @@ void Graphics::setDepthMode(CompareMode compare, bool write)
states.back().depthWrite = write;
}

void Graphics::setDepthClamp(bool enable)
{
flushBatchedDraws();

if (optionalDeviceExtensions.extendedDynamicState3)
{
vkCmdSetDepthClampEnableEXT(commandBuffers.at(currentFrame), Vulkan::getBool(enable));
}

states.back().depthClampEnable = enable;
}

void Graphics::setWireframe(bool enable)
{
flushBatchedDraws();
Expand Down Expand Up @@ -1357,6 +1369,11 @@ void Graphics::initDynamicState()
vkCmdSetFrontFaceEXT(
commandBuffers.at(currentFrame), Vulkan::getFrontFace(states.back().winding));
}

if (optionalDeviceExtensions.extendedDynamicState3)
{
vkCmdSetDepthClampEnableEXT(commandBuffers.at(currentFrame), Vulkan::getBool(states.back().depthClampEnable));
}
}

void Graphics::beginSwapChainFrame()
Expand Down Expand Up @@ -1782,6 +1799,8 @@ static void findOptionalDeviceExtensions(VkPhysicalDevice physicalDevice, Option
{
if (strcmp(extension.extensionName, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) == 0)
optionalDeviceExtensions.extendedDynamicState = true;
if (strcmp(extension.extensionName, VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME) == 0)
optionalDeviceExtensions.extendedDynamicState3 = true;
if (strcmp(extension.extensionName, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME) == 0)
optionalDeviceExtensions.memoryRequirements2 = true;
if (strcmp(extension.extensionName, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) == 0)
Expand Down Expand Up @@ -1844,6 +1863,8 @@ void Graphics::createLogicalDevice()
std::vector<const char*> enabledExtensions(deviceExtensions.begin(), deviceExtensions.end());
if (optionalDeviceExtensions.extendedDynamicState)
enabledExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
if (optionalDeviceExtensions.extendedDynamicState3)
enabledExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
if (optionalDeviceExtensions.memoryRequirements2)
enabledExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
if (optionalDeviceExtensions.dedicatedAllocation)
Expand Down Expand Up @@ -2609,13 +2630,23 @@ void Graphics::prepareDraw(VertexAttributesID attributesID, const BufferBindings
if (optionalDeviceExtensions.extendedDynamicState)
{
vkCmdSetCullModeEXT(commandBuffers.at(currentFrame), Vulkan::getCullMode(cullmode));
pipeline = s->getCachedGraphicsPipeline(this, configuration.core);
if (!optionalDeviceExtensions.extendedDynamicState3)
{
// If extended dynamic state 3 is not supported, we need to set the depth clamp enable manually via no dynamic state.
// But the depth clamp enable is not part of the core dynamic state, so we need to use noDynamicState only for depth clamp enable.
// Rest of the dynamic state is still set via extended dynamic state.
configuration.noDynamicState.depthClampEnable = states.back().depthClampEnable;
pipeline = s->getCachedGraphicsPipeline(this, configuration);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling getCachedGraphicsPipeline(this, configuration); rather than getCachedGraphicsPipeline(this, configuration.core); means all draws are going to be slower than before, in situations where extendedDynamicState is supported but extendedDynamicState3 is not.

(The hash map query is much slower with the larger struct than with the smaller one, it's a hot spot in user code so it's important to keep it as fast as possible).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah right, but since we are tracking a new variable, it's tracking more variants, so how about another structure noExtendedDynamicState passed alongside (smaller than noDynamicState), this way the code path is still hotter than original but no as hot as getCachedGraphicsPipeline(this, configuration);? Any other ideas to keep it same and still track variants?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could do something like getCachedGraphicsPipelineCoreWithDepthClamp or getCachedGraphicsPipelineExtendedDynamicState to maintain another set of variants with Core + dynamic_state3 variants?

}
else
pipeline = s->getCachedGraphicsPipeline(this, configuration.core);
}
else
{
configuration.noDynamicState.winding = states.back().winding;
configuration.noDynamicState.depthState.compare = states.back().depthTest;
configuration.noDynamicState.depthState.write = states.back().depthWrite;
configuration.noDynamicState.depthClampEnable = states.back().depthClampEnable;
configuration.noDynamicState.stencilAction = states.back().stencil.action;
configuration.noDynamicState.stencilCompare = states.back().stencil.compare;
configuration.noDynamicState.cullmode = cullmode;
Expand Down Expand Up @@ -3012,7 +3043,6 @@ VkPipeline Graphics::createGraphicsPipeline(Shader *shader, const GraphicsPipeli

VkPipelineRasterizationStateCreateInfo rasterizer{};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = Vulkan::getPolygonMode(configuration.wireFrame);
rasterizer.lineWidth = 1.0f;
Expand All @@ -3022,6 +3052,9 @@ VkPipeline Graphics::createGraphicsPipeline(Shader *shader, const GraphicsPipeli
rasterizer.frontFace = Vulkan::getFrontFace(noDynamicStateConfiguration->winding);
}

if (!optionalDeviceExtensions.extendedDynamicState3)
rasterizer.depthClampEnable = Vulkan::getBool(noDynamicStateConfiguration->depthClampEnable);

rasterizer.depthBiasEnable = VK_FALSE;
rasterizer.depthBiasConstantFactor = 0.0f;
rasterizer.depthBiasClamp = 0.0f;
Expand Down Expand Up @@ -3098,7 +3131,7 @@ VkPipeline Graphics::createGraphicsPipeline(Shader *shader, const GraphicsPipeli

std::vector<VkDynamicState> dynamicStates;

if (optionalDeviceExtensions.extendedDynamicState)
if (optionalDeviceExtensions.extendedDynamicState3)
dynamicStates = {
VK_DYNAMIC_STATE_SCISSOR,
VK_DYNAMIC_STATE_VIEWPORT,
Expand All @@ -3111,15 +3144,30 @@ VkPipeline Graphics::createGraphicsPipeline(Shader *shader, const GraphicsPipeli
VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
VK_DYNAMIC_STATE_STENCIL_OP_EXT,
};
VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT,
};
else if (optionalDeviceExtensions.extendedDynamicState)
dynamicStates = {
VK_DYNAMIC_STATE_SCISSOR,
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
VK_DYNAMIC_STATE_STENCIL_REFERENCE,

VK_DYNAMIC_STATE_CULL_MODE_EXT,
VK_DYNAMIC_STATE_FRONT_FACE_EXT,
VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
VK_DYNAMIC_STATE_STENCIL_OP_EXT,
};
else
dynamicStates = {
VK_DYNAMIC_STATE_SCISSOR,
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
VK_DYNAMIC_STATE_STENCIL_REFERENCE,
};
};

VkPipelineDynamicStateCreateInfo dynamicState{};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
Expand Down
4 changes: 4 additions & 0 deletions src/modules/graphics/vulkan/Graphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ struct OptionalDeviceExtensions
// VK_EXT_extended_dynamic_state
bool extendedDynamicState = false;

// VK_EXT_extended_dynamic_state3
bool extendedDynamicState3 = false;

// VK_KHR_get_memory_requirements2
bool memoryRequirements2 = false;

Expand Down Expand Up @@ -251,6 +254,7 @@ class Graphics final : public love::graphics::Graphics
void setScissor() override;
void setStencilState(const StencilState &s) override;
void setDepthMode(CompareMode compare, bool write) override;
void setDepthClamp(bool enable) override;
void setFrontFaceWinding(Winding winding) override;
void setColorMask(ColorChannelMask mask) override;
void setBlendState(const BlendState &blend) override;
Expand Down
1 change: 1 addition & 0 deletions src/modules/graphics/vulkan/Shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ struct GraphicsPipelineConfigurationNoDynamicState
StencilAction stencilAction = STENCIL_MAX_ENUM;
CompareMode stencilCompare = COMPARE_MAX_ENUM;
DepthState depthState{};
bool depthClampEnable = false;
};

struct GraphicsPipelineConfigurationFull
Expand Down
7 changes: 7 additions & 0 deletions src/modules/graphics/wrap_Graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2891,6 +2891,12 @@ int w_getDepthMode(lua_State *L)
return 2;
}

int w_setDepthClamp(lua_State *L)
{
instance()->setDepthClamp(luax_checkboolean(L, 1));
return 0;
}

int w_setMeshCullMode(lua_State *L)
{
const char *str = luaL_checkstring(L, 1);
Expand Down Expand Up @@ -4081,6 +4087,7 @@ static const luaL_Reg functions[] =
{ "getPointSize", w_getPointSize },
{ "setDepthMode", w_setDepthMode },
{ "getDepthMode", w_getDepthMode },
{ "setDepthClamp", w_setDepthClamp },
{ "setMeshCullMode", w_setMeshCullMode },
{ "getMeshCullMode", w_getMeshCullMode },
{ "setFrontFaceWinding", w_setFrontFaceWinding },
Expand Down
Loading