Direct3D12 - which RootSignature takes precedence? - hlsl

I'm new to MSFT and DirectX so please go easy on me..
If an hlsl shader uses the [RootSignature(SignatureName)] attribute, will it be overridden by a root signature defined in code using ID3D12RootSignature?
E.g. in sample code I have this in an .hlsli file which is included by a shader:
"RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \
"CBV(b0, visibility = SHADER_VISIBILITY_VERTEX), " \
"CBV(b0, visibility = SHADER_VISIBILITY_PIXEL), " \
"DescriptorTable(SRV(t0, numDescriptors = 6), visibility = SHADER_VISIBILITY_PIXEL)," \
"DescriptorTable(SRV(t64, numDescriptors = 6), visibility = SHADER_VISIBILITY_PIXEL)," \
"RootConstants(b1, num32BitConstants = 2, visibility = SHADER_VISIBILITY_VERTEX), " \
"StaticSampler(s0, maxAnisotropy = 8, visibility = SHADER_VISIBILITY_PIXEL)," \
"StaticSampler(s1, visibility = SHADER_VISIBILITY_PIXEL," \
"addressU = TEXTURE_ADDRESS_CLAMP," \
"addressV = TEXTURE_ADDRESS_CLAMP," \
"addressW = TEXTURE_ADDRESS_CLAMP," \
"comparisonFunc = COMPARISON_GREATER_EQUAL," \
"filter = FILTER_MIN_MAG_LINEAR_MIP_POINT)"
And in the shader:
[RootSignature(ModelViewer_RootSig)]
VSOutput main(VSInput vsInput)
{
VSOutput vsOutput;
vsOutput.position = mul(modelToProjection, float4(vsInput.position, 1.0));
vsOutput.worldPos = vsInput.position;
vsOutput.texCoord = vsInput.texcoord0;
vsOutput.viewDir = vsInput.position - ViewerPos;
<etc>
Will this override or be overridden by a root signature created with something like the following:
ASSERT_SUCCEEDED( g_Device->CreateRootSignature(1, pOutBlob->GetBufferPointer(), pOutBlob->GetBufferSize(), MY_IID_PPV_ARGS(&m_Signature)) );

On PC if you have both a "code-provided" Root Signature and a "shader-provided" Root Signature, the code one takes precedence. Generally you should use one or the other, not both.
For DirectX Tool Kit for DX12 on GitHub I use both in violation of what I just said above, but there's good reasons for it. In general the "code-style" Root Signature seems easier to understand for 'newbies', and therefore I make use of it in the tool kit since it's primarily intended for learning projects, samples, etc. I do also support Xbox development, where the strong recommendation is to always use shader-based root signatures.
This is because on Xbox the shaders are 'fully precompiled' and any difference in the root signature triggers a 'recompile' at runtime. The Xbox version of the runtime generates debug output if my code and shader signatures are out-of-sync, so it's easy enough for me to maintain. That's not true for most people. It also provides a bunch of examples of the same root sig in both code and shader notation, which is a good thing for deved, but probably not worthwhile for most projects.

Related

How to testing that Bazel my_test rule fails when it should?

I have found the documentation for how to test for expected analysis phase errors, but I'm drawing a blank no mater what I try to search for on how to test for expected execution phase failures.
An example of what I'm looking for would be a test of this example line_length_test rules where the test feeds in a file with over length lines and expects the test-under-test to be run and produce a failure.
Or to put it another way; I want a test that would fail if I did something dumb like this:
def _bad_test_impl(ctx):
# No-op, never fails regardless of what you feed it.
executable = ctx.actions.declare_file(ctx.label.name + ".sh")
ctx.actions.write(output=executable, content="")
return [DefaultInfo(executable=executable)]
bad_test = rule(
implementation=_bad_test_impl,
test=True,
)
Edit:
So far, the best I've come up with is the very gross:
BUILD
# Failure
bad_test(
name = "bad_test_fail_test",
tags = ["manual"],
)
native.sh_test(
name = "bad_test_failure_test",
srcs = [":not.sh"],
args = ["$(location :bad_test_fail_test)"],
data = [":bad_test_fail_test"],
)
not.sh
! $*
This does not seem like a good idea, particularly for something I'd expect to be well supported.
EDIT:
I got annoyed and built my own. I still wish there was official implementation.
I don't think that your not.sh is a particularly bad solution. But it depends on the situation. In general the Key to good failure testing is specificity i.e. this test should fail for this specific reason. If you don't get this nailed down your going to have a lot of headaches with false positives.
I'll use a slightly more expressive example to try and illustrate why it's so difficult to create a "generic/well supported" failure testing framework.
Let's say that we are developing a compiler. To test the compilers parser we intentionally feed the compiler a malformed source file, and we expect it to fail with something like a "missed semicolon on line 55". But instead our compiler fails from a fairly nasty bug that results in a segfault. As we have just tested that the compiler fails, the test passes.
This kind of a false positive is really hard to deal with in a way that is easy to reason about, whilst also being generic.
What we really want in the above scenario, is to test that the compiler fails AND it prints "missed semicolon on line 55". At this point it becomes increasingly difficult to create a "well supported" interface for these kinds of tests.
In reality a failure test is an integration test, or in some cases an end to end test.
Here is a short excerpt of an integration test from the Bazel repository. This integration test calls Bazel with a range of different flags some combinations expecting success and others failure;
function test_explicit_sandboxfs_not_found() {
create_hello_package
bazel build \
--experimental_use_sandboxfs \
--experimental_sandboxfs_path="/non-existent/sandboxfs" \
//hello >"${TEST_log}" 2>&1 && fail "Build succeeded but should have failed"
expect_log "Failed to get sandboxfs version.*/non-existent/sandboxfs"
}
And the corresponding build definition;
sh_test(
name = "sandboxfs_test",
size = "medium",
srcs = ["sandboxfs_test.sh"],
data = [":test-deps"],
tags = ["no_windows"],
)

Generating message type with preprocessor

I want to create a communication protocol between two microcontrollers, I use class logic that incorporates message types between systems. I want to develop a more simple process of creating new messages by doing something very simple like following
BEGIN_MSG(LinearDriveMsg)
ADD_2BIT(DriveSpeed, speed)
ADD_16BIT(GMath::Position, position.x)
END_MSG
Ideally it would expand to:
BEGIN_MSG(LinearDriveMsg)
BEGIN_SERIALIZER
ADD_SERIALIZER_2BIT(DriveSpeed, speed)
ADD_SERIALIZER_16BIT(GMath::Position, position.x)
END_SERIALIZER
BEGIN_DESERIALIZER
ADD_DESERIALIZER_2BIT(DriveSpeed, speed)
ADD_DESERIALIZER_16BIT(GMath::Position, position.x)
END_DESERIALIZER
END_MSG
And then expand to cpp code
...
bool LinearDriveMsg::deserialize(const uint8_t *incoming_buffer, const uint8_t *incoming_size) override{
if (*incoming_size != getMessageSize())
return false;
_speed = (DriveSpeed)((incoming_buffer[0] & SPEED_MASK) >> SPEED_OFFSET);
weldTwoBytesToInt(&incoming_buffer[1], _position.x);
return true;
}
int LinearDriveMsg::serialize(uint8_t *outgoing_buffer, uint8_t *outgoing_size) const override{
if (*outgoing_size < getMessageSize())
return -1;
outgoing_buffer[0] |= ((uint8_t)_speed << SPEED_OFFSET) & SPEED_MASK;
cutIntToTwoBytes(_position.x, outgoing_buffer + 1, 2);
return getMessageSize();
}
...
I know that doing some advanced preprocessor stuff is pretty tricky but maybe there some way to do this task? It is also possible to adjust the actual cpp code to make it possible (in that way that the efficiency is still ok)
I will answer it myself. There is actually "simple" way to solve above task in preprocessor. The boost library offers tools to work approximately in preprocessor like in normal languages. They have a package called preprocessor as part of the boost suite read the docs, you can download it here it is part of the main package.
Main feature that helped to solve the task above was the idea to forward a tuple of arrays to constructs that we know from functional programming. Actually it is BOOST_PP_SEQ_FOR_EACH(macro, data, seq). Another feature that helped to solve the task was this guys implementation to create double parentheses around each element.
As idea it will work like following. I have the above list of tuples:
#define frame_composition (begin_byte(0), begin_bit(0), int8_t, speed)\
(begin_byte(1), begin_bit(4), int16_t, direction)\
I have somekind of sequence of actions, because I want to have serial first and deserial second:
#define COMPOSE_FRAME(seq) \
ADD_SERIAL(seq) \
ADD_DESERIAL(seq)
Now the content of each add category:
#define ADD_SERIAL(seq) \
BOOST_PP_SEQ_FOR_EACH(ADD_SERIAL_ELEM, ~, GLK_PP_SEQ_DOUBLE_PARENS(seq))
#define ADD_DESERIAL(seq) \
BOOST_PP_SEQ_FOR_EACH(ADD_DESERIAL_ELEM, ~, GLK_PP_SEQ_DOUBLE_PARENS(seq)) \
The cool thing is, we have forwarded the same list of tuples to different constructs, to execute some different algorithms. Now the contents of X_ELEM defines:
#define ADD_SERIAL_ELEM(seq) \
outgoing_buffer[BOOST_PP_TUPLE_ELEM( 0, elem)] = (uint8_t) BOOST_PP_TUPLE_ELEM( 3, elem);
#define ADD_DESERIAL_ELEM(seq) \
BOOST_PP_TUPLE_ELEM(3,elem) = (BOOST_PP_TUPLE_ELEM(2,elem)) incoming_buffer[BOOST_PP_TUPLE_ELEM(0,elem)];
And if you need you can distinguish between different use cases in element "functions" with
BOOST_PP_IF(cond, t, f)
To do different things for example on object and simple variables
This is noway complete solution, but to see the idea and that it is possible to create highly portable simple message generator framework out of cpp.

Use of [bazel] restricted_to attribute

I'm trying to use the bazel restricted_to attribute for a test.
I want the test to only run on a specific cpu = build.
To make this somewhat more complicated, the cpu type is defined in our
/tools/cpp/CROSSTOOL file (cpu=armhf-debian).
I've had no luck with guessing the syntax of the restricted_to parameter
(my first guess was //cpu:armhf-debian, which just looked for a cpu package)
Any Suggestions?
There's not a lot of documentation on restricted_to, and the other rules it works with, environment and environment_group. Mostly this is because the use case they are for is very specific to Google's repository setup, and we're in the process of replacing them with a more flexible system.
To use restricted_to, you would need to define several environment rules, and an environment_group to contain them, and then specify which environment the test is restricted to, and finally always use the "--target_environment" flag to specify the current environment group. That would look something like this:
environment(name = "x86")
environment(name = "ppc")
environment_group(
name = "cpus",
defaults = [":x86"],
environments = [
":x86",
":ppc",
])
cc_test(
name = "test",
other config
restricted_to = [":ppc"],)
You could then run the test as so:
bazel test --target_environment=//:ppc //:test
to get the environment checking.
This isn't terribly useful, as whoever is running the test has to also remember to set "--target_environment" properly.
A better way to disable the test, using currently supported code, is to use config_setting and select, like this:
config_setting(
name = "k8",
values = {"cpu": "k8"})
config_setting(
name = "ppc",
values = {"cpu":, "ppc")
cc_test(
name = "test",
other config
srcs = [other sources] +
select({
"//:x86": ["x86_test_src.cpp"],
"//:ppc": ["ppc_test_src.cpp"],
"//conditions:default": ["default_test_src.cpp"],
})
config_setting will take a value based on the current "--cpu" flag. By changing the files included in the select, you can control what files are included in the test for each cpu setting.
Obviously, these don't have to be in the same package, and the usual Bazel visibility rules apply. See Bazel's src/BUILD for an example of config_setting, and src/test/cpp/BUILD for an example of using it in select.
We're working hard on platforms, which is a better way to describe and query Bazel's execution environment, and we'll make sure to post documentation and a blog post when that's ready for people to test.

Making files with map or scenario information, such as what resources to load, objects, locations, events

I'm making a simple graphics engine in C++, using Visual C++ and DirectX, and I'm testing out different map layouts.
Currently, I construct "maps" by simply making a C++ source file and start writing:
SHADOWENGINE ShadowEngine(&settings);
SPRITE_SETTINGS sset;
MODEL_SETTINGS mset;
sset.Name = "Sprite1";
sset.Pivot = TOPLEFT;
sset.Source = "sprite1.png";
sset.Type = STATIC;
sset.Movable = true;
sset.SoundSet = "sprite1.wav"
ShadowEngine->Sprites->Load(sset);
sset.Name = "Sprite2"
sset.Source = "sprite2.png";
sset.Parent = "Sprite1";
sset.Type = ANIMATED;
sset.Frames = 16;
sset.Interval = 1000;
sset.Position = D3DXVECTOR(0.0f, (ShadowEngine->Resolution->Height/2), 0.0f);
ShadowEngine->Sprites->Load(sset);
mset.Source = "character.sx";
mset.Collision = false;
mset.Type = DYNAMIC;
ShadowEngine->Models->Load(mset);
//Etc..
What I'd like to be able to do, is to create map files that are instead loaded into the engine, without having to write them into the executable. That way, I can make changes to the maps without having to recompile every damn time.
SHADOWENGINE ShadowEngine(&settings);
ShadowEngine->InitializeMap("Map1.sm");
The only way I can think of is to make it read the file as text and then just parse the information, but it sounds like such a hassle.
Am I thinking the wrong way?
What should I do?
Wouldn't mind an explanation on how others do it, like Warcraft III, Starcraft, Age of Empires, Heroes of Might and Magic...
Would really appreciate some help on this one.
You are not thinking the wrong way, loading your map data is definitely desirable. The most common prebuilt solutions are Protocol Buffers and Lua. If you don't already know Lua I would use protocol buffers, as it directly solves your problem, whereas Lua is a scripting language which is flexible enough to do what you need done.
Some people write their data as XML, but this is only a partial solution as XML is just a markup language. After loading the XML you'll have a DOM tree to parse.
Google's CPP Protobuf Tutorial

C++ code generation for repeated task

I have something like below which will get repeated many times based on the function
that get called
for e.g
acceptfunction()
{
inserter["quantity"] = sdd.getfloat(quantity);
inserter["prodtype"] = sdd.getstring(prodtype);
:
:
so on
}
Like accept above there are 20 more functions(reject,cancel etc) which will do the
similar thing.But the parameteres they insert can differ based on function called.
How can I automate this kind of code.So that I dont need to write new function from
scratch.Basically what I need is if i provide parametres like ("quantity",prodtype)
through some text file or xml, it should generate the required function with the
input parametres.
Is this task can be handled through C++ tempalte Meta programming or someother code
generation tool will help me to do this?
It's ugly, but you can use a preprocessor macro:
#define FUNCTION_MACRO(NAME, ATTRIB1, ATTRIB2)\
void NAME()\
{\
inserter[#ATTRIB1] = sdd.getfloat(ATTRIB1);\
inserter[#ATTRIB2] = sdd.getstring(ATTRIB2);\
}
And then to create a function you just need to do:
FUNCTION_MACRO(accept_function, quantity, prodtype)
Well, when it comes down do it, you almost certainly could but it would require implementing an XML or text parser in TMP. Would be quite a feat.
That's not how things would normally be done, but you've not specified enough details to go into it further.
Macros are generally to be avoided, but this is a case where they are still useful. Something like
#define GET_FUNCTION(type, name) \
do \
{ \
inserter[#name] = sdd.get ## type(name); \
} \
while (0)
will let you say
void acceptfunction()
{
GET_FUNCTION(float, quantity);
GET_FUNCTION(string, prodtype);
// etc...
}
(The reason for the odd do-while construct is to guarantee that the result is a single statement.)
Define different macros for rejectfunction(), etc.