Tutorial 128: Load Compiled XNA Effects on Supported Renderers

CNA Tutorials  ·  CNA 0.1.0-alpha.1

Format first: alpha.1 accepts XNA/FNA D3D9 Effect Framework binary bytecode (commonly stored as .fxb), including the XNA 4 wrapper and an Effect payload inside XNB. It does not compile HLSL .fx source and does not accept DXBC or MonoGame MGFX/.mgfxo.

Choose a capable renderer build

Renderer familyAlpha.1 configuration
FNA3DCompiled effects enabled by the renderer path
EasyGL identities-DCNA_EASYGL_COMPILED_EFFECTS=ON
SDL_GPU-DCNA_SDL_GPU_COMPILED_EFFECTS=ON
Vulkan-DCNA_VULKAN_COMPILED_EFFECTS=ON
Every other familyCompiledEffects capability is false
cmake -S ../cna -B build-fx \
  -DCNA_GRAPHICS_RENDERER=OPENGLES3 \
  -DCNA_EASYGL_COMPILED_EFFECTS=ON

The three opt-in options default to OFF because they add MojoShader/FNA3D Effect Framework machinery and renderer-specific integration. Enabling an option for one family is not a universal capability promise.

Construct an Effect from bytes

#include "Microsoft/Xna/Framework/Graphics/Effect.hpp"
#include "CNA/GraphicsCapability.hpp"

using Microsoft::Xna::Framework::Graphics::Effect;
using CNA::GraphicsCapability;

auto& device = getGraphicsDeviceProperty();
if (!device.SupportsCapability(GraphicsCapability::CompiledEffects))
{
    throw std::runtime_error("This renderer build cannot load compiled XNA effects");
}

std::vector<SharpRuntime::bytecs> effectCode = ReadAllBytes("Content/water.fxb");
auto effect = std::make_unique<Effect>(device, effectCode);

auto& technique = effect->getTechniquesProperty()[0];
effect->setCurrentTechniqueProperty(&technique);
for (auto& pass : technique.getPassesProperty())
{
    pass.Apply();
    DrawWaterGeometry();
}

The public constructor validates empty, malformed and oversized input (64 MiB maximum). It reflects techniques, passes, parameters, annotations, arrays and structures; applies pass state; supports independent clones; and can participate in SpriteBatch and ordinary 3D drawing.

Load through ContentManager and EffectReader

#include "Microsoft/Xna/Framework/Graphics/Effect.hpp"

auto effect = getContentProperty().Load<std::shared_ptr<
    Microsoft::Xna::Framework::Graphics::Effect>>(
        "Effects/water"); // resolves the .xnb asset

The XNB built-in registry contains a real EffectReader. It extracts the same compiled payload and creates the same renderer-qualified runtime. An active graphics device is required; an XNB file does not make unsupported renderer builds capable.

Set parameters and apply passes

Use the reflected Parameters, Techniques and Passes collections as in XNA. The compiled runtime stores parameter values, applies pass state, and keeps clone state independent. This is a separate path from CNAEXT ShaderEffect, whose uniforms are set through SetUniformXxx() and whose input is renderer-native source/binary.

Interpret failures precisely

  • ArgumentException: empty, oversized, malformed or wrong Effect Framework payload.
  • NotSupportedException: active renderer lacks CompiledEffects, or the input is a recognized unsupported container such as MGFX.
  • A source file named .fx is not compiled at runtime. Compile it with an XNA/FNA-compatible Effect Framework toolchain before packaging.

Next steps