I have been trying now for 2 days, to bind two different bitmap textures to a HLSL shader I am currently developing. Binding the first texture to the first binding and only sampling this and returning the color directly works as expected, oddly enough, using also the first texture, that worked before for the first slot, does not work if I also bind it to the second slot I am using. I only get a black screen then. I am loading the second texture with opencv, and the first texture is a result of previous shader operations and also proven to work as explained above.
This is the code to load the second texture:
cv::Mat png_image =
cv::imread("<path to png, also confirmed>", cv::IMREAD_UNCHANGED);
if (!png_image.data)
{
ASSERT(false);
}
ASSERT(4 == png_image.channels());
// and then the texture data is successfully uploaded to the GPU,
// this also has to work as the same function has been used multiple times before
This is my custom effect:
// BaseCustomEffect extends from "public ID2D1EffectImpl, public ID2D1DrawTransform"
// and those implement the "Initialize", "PrepareForRender" and "SetGraph"
class CustomEffect : public BaseCustomEffect
{
private:
CustomEffect();
public:
//! Register effect
static HRESULT Register(ID2D1Factory1* pFactory);
static HRESULT __stdcall CreateCustomEffect(IUnknown** ppEffectImpl);
};
CustomEffect::CustomEffect()
{
// BLOT_CustomShader is the compiled binary of the shader (compiled successfully).
m_shaderBlob = BLOT_CustomShader;
m_shaderBlobSize = _ARRAYSIZE(BLOT_CustomShader);
m_shaderGUID = GUID_CustomEffectShader;
}
#define XML(X) TEXT(#X)
HRESULT CustomEffect::Register(ID2D1Factory1* pFactory)
{
// The inspectable metadata of an effect is defined in XML. This can be passed in from an
// external source as well, however for simplicity we just inline the XML.
PCWSTR pszXml = XML
(
<?xml version = '1.0'?>
<Effect>
<!--System Properties-->
<Property name = 'DisplayName' type = 'string' value = 'Custom Effect' />
<Property name = 'Author' type = 'string' value = '<author>' />
<Property name = 'Category' type = 'string' value = '<category>' />
<Property name = 'Description' type = 'string' value = 'Custom effect.' />
<Inputs minimum = '2' maximum = '2'>
<Input name = 'Source' />
<Input name = 'CustomTexture' />
</Inputs>
</Effect>
);
// Must match name attribute in XML.
const D2D1_PROPERTY_BINDING bindings[] =
{
// this is set here, but not relevant for the problem
// D2D1_VALUE_TYPE_BINDING(L"Intensity", &SetIntensity, &GetIntensity),
};
return pFactory->RegisterEffectFromString(GUID_CustomEffectShader, pszXml, bindings, _ARRAYSIZE(bindings), CreateCustomEffect);
}
HRESULT __stdcall CustomEffect::CreateCustomffect(IUnknown** ppEffectImpl)
{
*ppEffectImpl = static_cast<ID2D1EffectImpl*>(new CustomEffect());
return (nullptr == *ppEffectImpl) ? E_OUTOFMEMORY : S_OK;
}
This is the rendering of my custom effect:
inD2DContext->SetTarget(inTargetBmp);
inD2DContext->BeginDraw();
inD2DContext->Clear(D2D1::ColorF(D2D1::ColorF::Black, 0.f));
inConversion.mEffect->SetInputCount(2);
inConversion.mEffect->SetInput(0, inSourceBmp);
inConversion.mEffect->SetInput(1, texture->GetData()->GetD2dBitmap());
inD2DContext->DrawImage(inConversion.mEffect);
inD2DContext->EndDraw();
The context is valid, the conversion (just a simple wrapper around the effect) is valid, the effect is loaded properly and I asserted previously on the bitmap of the second texture, so it is not nullptr as well.
This is my current HLSL shader code:
#define D2D_INPUT_COUNT 2
Texture2D InputTexture : register(t0); // works, if I sample using the InputSampler, as expected
Texture2D CustomTexture : register(t1); // does not work
SamplerState InputSampler : register(s0);
SamplerState CustomSampler : register(s1);
/*
// not relevant here
cbuffer constants : register(b0)
{
float Intensity : packoffset(c0);
};
*/
float4 main(
float4 pos : SV_POSITION,
float4 posScene : SCENE_POSITION,
float2 uv0 : TEXCOORD0
) : SV_Target
{
#if 1
// works
//return float4(1, 0, 0, 1);
// not working
//return CustomTexture.Sample(InputSampler, uv0);
// also not working, not expected, as the uvs are now hardcoded
return CustomTexture.Sample(CustomSampler, float2(0.5f, 0.5f));
// also not working, this should output the custom texture itself and display it to the screen
//return CustomTexture.Sample(CustomSampler, uv0);
#else
// actual shader code, not relevant here
#endif
}
I tested the second slot also with the first texture, it didn't work either, so I think the second binding is generally not working and has nothing to do with the texture not loaded or transferred correctly. Did anyone have a similar issue before? In all my research through the microsoft docs and stackoverflow, I wasn't able to find another dev with the same problem. If anyone has a solution or an idea, I would be very happy, if you could share it!
Thanks for reading and your time.