Skip to content
Merged
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
57 changes: 57 additions & 0 deletions mesa_warning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from bpy.types import Context, Event, Operator


class MesaWarningPopup(Operator):
bl_label = "Mesa Driver Limitations"
bl_idname = "dialog.f64_mesa_warning"
bl_description = "Update color management settings to help material preview accuracy"
bl_options = {"UNDO"}

already_invoked = False # HACK: used to prevent multiple dialogs from popping up

def invoke(self, context: Context, event: Event):
prefs = context.preferences.addons[__name__.split(".")[0]].preferences
if prefs.dont_warn_about_mesa:
return {"CANCELLED"}
if MesaWarningPopup.already_invoked:
return {"FINISHED"}
MesaWarningPopup.already_invoked = True
return context.window_manager.invoke_props_dialog(self, width=400)

def draw(self, context: Context):
from fast64_internal.utility import multilineLabel

col = self.layout.column()
col.label(text="You are using Mesa drivers!", icon="MEMORY")
multilineLabel(
col,
(
(
"These are much more strict as opposed to commercial drivers\n"
"and do not allow us to enable helpful extensions!"
)
),
)
col.alert = True
col.label(text="This will hinder your accuracy and or performance.", icon="ERROR")
col.alert = False
multilineLabel(
col,
(
(
'You can add "allow_glsl_extension_directive_midshader=true" to your\n'
"blender launch arguments to bypass this restriction, or change render\n"
"device."
)
),
icon="INFO",
)

prefs = context.preferences.addons[__name__.split(".")[0]].preferences
col.prop(prefs, "dont_warn_about_mesa", text="Don't warn me again")

def cancel(self, context: Context):
MesaWarningPopup.already_invoked = False

def execute(self, context):
return {"FINISHED"}
32 changes: 21 additions & 11 deletions properties.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import bpy
from bpy.types import PropertyGroup, Image
from bpy.types import PropertyGroup, Image, AddonPreferences
from bpy.props import BoolProperty

from .globals import F64_GLOBALS

Expand Down Expand Up @@ -163,13 +164,6 @@ def rebuild_shaders(_scene, _context):


class F64RenderSettings(bpy.types.PropertyGroup):
use_atomic_rendering: bpy.props.BoolProperty(
name="Use Atomic Rendering",
default=True,
description="Atomic rendering will draw to a depth and color buffer seperately, which allows for proper blender and decal emulation.\n"
"This may cause artifacts if your GPU does not support the interlock extension",
update=rebuild_shaders,
)
sources_tab: bpy.props.BoolProperty(name="Default Sources")
default_prim_color: bpy.props.FloatVectorProperty(
description="Primitive Color",
Expand Down Expand Up @@ -268,8 +262,6 @@ def draw_props(self, layout: bpy.types.UILayout, gameEditorMode: str):
prop_split(layout, self, "oot_specific_room", "Specific Room")
layout.separator()

if bpy.app.version >= (4, 1, 0):
layout.prop(self, "use_atomic_rendering")
layout.prop(self, "always_set")
layout.prop(self, "sources_tab", icon="TRIA_DOWN" if self.sources_tab else "TRIA_RIGHT")
if self.sources_tab:
Expand Down Expand Up @@ -300,5 +292,23 @@ def draw_props(self, layout: bpy.types.UILayout, gameEditorMode: str):
tex_prop.draw_default_ui(texture_box, i)


class F64RenderProperties(bpy.types.PropertyGroup):
class F64RenderProperties(PropertyGroup):
render_settings: bpy.props.PointerProperty(type=F64RenderSettings)


class F64AddonPreferences(AddonPreferences):
bl_idname = __name__.split(".")[0]

use_atomic_rendering: bpy.props.BoolProperty(
name="Use Atomic Rendering",
default=True,
description="Atomic rendering will draw to a depth and color buffer seperately, which allows for proper blender and decal emulation.\n"
"This may cause artifacts if your GPU does not support the interlock extension",
update=rebuild_shaders,
)
dont_warn_about_mesa: BoolProperty()

def draw_props(self, layout: bpy.types.UILayout):
atomic_col = layout.column()
atomic_col.prop(self, "use_atomic_rendering")
atomic_col.enabled = bpy.app.version >= (4, 1, 0)
59 changes: 55 additions & 4 deletions renderer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from io import StringIO
import math
import os
import pathlib
import sys
import time

import bpy
Expand Down Expand Up @@ -39,6 +41,27 @@ def materials_set_light_direction(scene):
return not (scene.gameEditorMode == "SM64" and scene.fast64.sm64.matstack_fix)


def flag_enabled(flag_name: str) -> bool:
true_values = {"1", "true", "yes", "on"}

if os.environ.get(flag_name, "").lower() in true_values:
return True

return False


def check_if_under_mesa():
vendor = gpu.platform.vendor_get()
renderer = gpu.platform.renderer_get()
version = gpu.platform.version_get()
combined = (vendor + renderer + version).lower()
return "mesa" in combined or "llvmpipe" in combined


def show_mesa_warning():
bpy.ops.dialog.f64_mesa_warning("INVOKE_DEFAULT")


class Fast64RenderEngine(bpy.types.RenderEngine):
bl_idname = "FAST64_RENDER_ENGINE"
bl_label = "Fast64 Renderer"
Expand Down Expand Up @@ -72,14 +95,37 @@ def __init__(self, *args, **kwargs):
# Create a 1x1 image
bpy.data.images.new("f64render_missing_texture", 1, 1).pixels = MISSING_TEXTURE_COLOR

ext_list = gpu.capabilities.extensions_get()
self.is_mesa_driver = check_if_under_mesa()
if self.is_mesa_driver:
print("Mesa drivers detected!")
self.allow_glsl_extension_directive_midshader = not self.is_mesa_driver or flag_enabled(
"allow_glsl_extension_directive_midshader"
)
if self.is_mesa_driver:
if self.allow_glsl_extension_directive_midshader:
print(
'Sucefully bypassed Mesa restriction on GLSL extensions via "allow_glsl_extension_directive_midshader"!'
)
else:
print("GLSL extension directives mid-shader are disabled!")

if self.allow_glsl_extension_directive_midshader:
ext_list = gpu.capabilities.extensions_get()
else:
ext_list = []
self.shader_interlock_support = "GL_ARB_fragment_shader_interlock" in ext_list
if not self.shader_interlock_support:
print("\n\nWarning: GL_ARB_fragment_shader_interlock not supported!\n\n")
print("Warning: GL_ARB_fragment_shader_interlock not supported!")
self.shader_derivative_control_support = "GL_ARB_derivative_control" in ext_list
if not self.shader_derivative_control_support:
print("Warning: GL_ARB_derivative_control not supported!")
if bpy.app.version < (4, 1, 0):
print("\n\nWarning: Blender version too old! Expect limited blending emulation!\n\n")
print("Warning: Blender version too old! Expect limited blending emulation!")
self.draw_range_impl = bpy.app.version >= (3, 6, 0)

if not self.allow_glsl_extension_directive_midshader and self.is_mesa_driver:
bpy.app.timers.register(show_mesa_warning)

def __del__(self):
def remove_handler(handler, func):
while func in handler:
Expand Down Expand Up @@ -133,6 +179,8 @@ def init_shader(self, scene: bpy.types.Scene):
shader_info.define("depth_unchanged", "depth_any")
if self.shader_interlock_support:
shader_info.define("USE_SHADER_INTERLOCK", "1")
if self.shader_derivative_control_support:
shader_info.define("USE_DERIVATIVE_CONTROL", "1")
shader_info.define("BLEND_EMULATION", "1")
# Using the already calculated view space normals instead of transforming the light direction makes
# for cleaner and faster code
Expand Down Expand Up @@ -279,7 +327,8 @@ def draw_scene(self, context, depsgraph):
f64render_rs: F64RenderSettings = depsgraph.scene.f64render.render_settings
always_set = f64render_rs.always_set
projection_matrix, view_matrix = context.region_data.perspective_matrix, context.region_data.view_matrix
self.use_atomic_rendering = bpy.app.version >= (4, 1, 0) and f64render_rs.use_atomic_rendering
prefs = context.preferences.addons[__name__.split(".")[0]].preferences
self.use_atomic_rendering = bpy.app.version >= (4, 1, 0) and prefs.use_atomic_rendering

if F64_GLOBALS.rebuild_shaders or self.shader is None:
F64_GLOBALS.rebuild_shaders = False
Expand Down Expand Up @@ -364,6 +413,8 @@ class F64RenderSettingsPanel(bpy.types.Panel):
def draw(self, context):
f64render_rs: F64RenderSettings = context.scene.f64render.render_settings
f64render_rs.draw_props(self.layout, context.scene.gameEditorMode)
prefs = context.preferences.addons[__name__.split(".")[0]].preferences
prefs.draw_props(self.layout)


def draw_render_settings(self, context: bpy.types.Context):
Expand Down
6 changes: 5 additions & 1 deletion shader/main3d.frag.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
layout(pixel_interlock_unordered) in;
#endif

#ifdef USE_DERIVATIVE_CONTROL
#extension GL_ARB_derivative_control : enable
#endif

#define DECAL_DEPTH_DELTA 100

vec3 cc_fetchColor(in int val, in vec4 shade, in vec4 comb, in float lodFraction, in vec4 texData0, in vec4 texData1)
Expand Down Expand Up @@ -144,7 +148,7 @@ void main()

vec4 ccShade = geoModeSelect(G_SHADE_SMOOTH, cc_shade_flat, cc_shade);

#ifdef GL_ARB_derivative_control
#ifdef USE_DERIVATIVE_CONTROL
const vec2 dx = abs(vec2(dFdxCoarse(inputUV.x), dFdyCoarse(inputUV.x)));
const vec2 dy = abs(vec2(dFdxCoarse(inputUV.y), dFdyCoarse(inputUV.y)));
#else
Expand Down
4 changes: 0 additions & 4 deletions shader/textures.glsl
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
#ifdef GL_ARB_derivative_control
#extension GL_ARB_derivative_control : enable
#endif

vec4 quantize3Bit(in vec4 color) {
return vec4(round(color.rgb * 8.0) / 8.0, step(0.5, color.a));
}
Expand Down