How can you convert a DXGI_FORMAT to a bpp (bit per pixel) value without enumeration? (see formats)
e.g.:
DXGI_FORMAT_R10G10B10A2_UNORM -> 32
DXGI_FORMAT_B5G5R5A1_UNORM -> 16
DirectXTex implements this utility function, and I have it internally in DirectX Tool Kit for DDSTextureLoader.
//-------------------------------------------------------------------------------------
// Returns bits-per-pixel for a given DXGI format, or 0 on failure
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
size_t DirectX::BitsPerPixel(DXGI_FORMAT fmt)
{
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32A32_FLOAT:
case DXGI_FORMAT_R32G32B32A32_UINT:
case DXGI_FORMAT_R32G32B32A32_SINT:
return 128;
case DXGI_FORMAT_R32G32B32_TYPELESS:
case DXGI_FORMAT_R32G32B32_FLOAT:
case DXGI_FORMAT_R32G32B32_UINT:
case DXGI_FORMAT_R32G32B32_SINT:
return 96;
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
case DXGI_FORMAT_R16G16B16A16_FLOAT:
case DXGI_FORMAT_R16G16B16A16_UNORM:
case DXGI_FORMAT_R16G16B16A16_UINT:
case DXGI_FORMAT_R16G16B16A16_SNORM:
case DXGI_FORMAT_R16G16B16A16_SINT:
case DXGI_FORMAT_R32G32_TYPELESS:
case DXGI_FORMAT_R32G32_FLOAT:
case DXGI_FORMAT_R32G32_UINT:
case DXGI_FORMAT_R32G32_SINT:
case DXGI_FORMAT_R32G8X24_TYPELESS:
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
case DXGI_FORMAT_Y416:
case DXGI_FORMAT_Y210:
case DXGI_FORMAT_Y216:
return 64;
case DXGI_FORMAT_R10G10B10A2_TYPELESS:
case DXGI_FORMAT_R10G10B10A2_UNORM:
case DXGI_FORMAT_R10G10B10A2_UINT:
case DXGI_FORMAT_R11G11B10_FLOAT:
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
case DXGI_FORMAT_R8G8B8A8_UINT:
case DXGI_FORMAT_R8G8B8A8_SNORM:
case DXGI_FORMAT_R8G8B8A8_SINT:
case DXGI_FORMAT_R16G16_TYPELESS:
case DXGI_FORMAT_R16G16_FLOAT:
case DXGI_FORMAT_R16G16_UNORM:
case DXGI_FORMAT_R16G16_UINT:
case DXGI_FORMAT_R16G16_SNORM:
case DXGI_FORMAT_R16G16_SINT:
case DXGI_FORMAT_R32_TYPELESS:
case DXGI_FORMAT_D32_FLOAT:
case DXGI_FORMAT_R32_FLOAT:
case DXGI_FORMAT_R32_UINT:
case DXGI_FORMAT_R32_SINT:
case DXGI_FORMAT_R24G8_TYPELESS:
case DXGI_FORMAT_D24_UNORM_S8_UINT:
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
case DXGI_FORMAT_R8G8_B8G8_UNORM:
case DXGI_FORMAT_G8R8_G8B8_UNORM:
case DXGI_FORMAT_B8G8R8A8_UNORM:
case DXGI_FORMAT_B8G8R8X8_UNORM:
case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
case DXGI_FORMAT_AYUV:
case DXGI_FORMAT_Y410:
case DXGI_FORMAT_YUY2:
case XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT:
case XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT:
case XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM:
return 32;
case DXGI_FORMAT_P010:
case DXGI_FORMAT_P016:
case XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT:
case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS:
case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT:
case WIN10_DXGI_FORMAT_V408:
return 24;
case DXGI_FORMAT_R8G8_TYPELESS:
case DXGI_FORMAT_R8G8_UNORM:
case DXGI_FORMAT_R8G8_UINT:
case DXGI_FORMAT_R8G8_SNORM:
case DXGI_FORMAT_R8G8_SINT:
case DXGI_FORMAT_R16_TYPELESS:
case DXGI_FORMAT_R16_FLOAT:
case DXGI_FORMAT_D16_UNORM:
case DXGI_FORMAT_R16_UNORM:
case DXGI_FORMAT_R16_UINT:
case DXGI_FORMAT_R16_SNORM:
case DXGI_FORMAT_R16_SINT:
case DXGI_FORMAT_B5G6R5_UNORM:
case DXGI_FORMAT_B5G5R5A1_UNORM:
case DXGI_FORMAT_A8P8:
case DXGI_FORMAT_B4G4R4A4_UNORM:
case WIN10_DXGI_FORMAT_P208:
case WIN10_DXGI_FORMAT_V208:
return 16;
case DXGI_FORMAT_NV12:
case DXGI_FORMAT_420_OPAQUE:
case DXGI_FORMAT_NV11:
return 12;
case DXGI_FORMAT_R8_TYPELESS:
case DXGI_FORMAT_R8_UNORM:
case DXGI_FORMAT_R8_UINT:
case DXGI_FORMAT_R8_SNORM:
case DXGI_FORMAT_R8_SINT:
case DXGI_FORMAT_A8_UNORM:
case DXGI_FORMAT_AI44:
case DXGI_FORMAT_IA44:
case DXGI_FORMAT_P8:
case XBOX_DXGI_FORMAT_R4G4_UNORM:
return 8;
case DXGI_FORMAT_R1_UNORM:
return 1;
case DXGI_FORMAT_BC1_TYPELESS:
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB:
case DXGI_FORMAT_BC4_TYPELESS:
case DXGI_FORMAT_BC4_UNORM:
case DXGI_FORMAT_BC4_SNORM:
return 4;
case DXGI_FORMAT_BC2_TYPELESS:
case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC2_UNORM_SRGB:
case DXGI_FORMAT_BC3_TYPELESS:
case DXGI_FORMAT_BC3_UNORM:
case DXGI_FORMAT_BC3_UNORM_SRGB:
case DXGI_FORMAT_BC5_TYPELESS:
case DXGI_FORMAT_BC5_UNORM:
case DXGI_FORMAT_BC5_SNORM:
case DXGI_FORMAT_BC6H_TYPELESS:
case DXGI_FORMAT_BC6H_UF16:
case DXGI_FORMAT_BC6H_SF16:
case DXGI_FORMAT_BC7_TYPELESS:
case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB:
return 8;
default:
return 0;
}
}
Of course, the real question is why do you need it?
You can simply create a function with switch statement:
int getBPP(DXGI_FORMAT format)
{
switch(format)
{
case DXGI_FORMAT_R16G16B16A16_UNORM: return 16*4;
case DXGI_FORMAT_R32G32B32A32_FLOAT: return 32*4;
//...
}
}
Alternatively, you could rely on the fact that the formats generally are grouped by their BPP. This is not strictly true - for example, there are multiple groups of 32bpp formats, but this could be handled with additional conditionals. For example:
int getBPP(DXGI_FORMAT format)
{
//...
else if (format >= DXGI_FORMAT_R32_TYPELESS &&
format <= DXGI_FORMAT_X24_TYPELESS_G8_UINT)
{
return 32;
}
else if (format >= DXGI_FORMAT_R9G9B9E5_SHAREDEXP &&
format <= DXGI_FORMAT_G8R8_G8B8_UNORM)
{
return 32;
}
//...
}
This of course relies on the assumption that the DXGI_FORMAT enum won't change and break this convention (although, that's pretty unlikely).
There is no utilities to perform the conversion for you, most 3d engine just implement their own with a basic large switch case. Also, the value you list are wrong, unless you consider the per component bits and not the whole pixel.
int DxgiFormat2Bpp( DXGI_FORMAT fmt ) {
switch(fmt) {
// many cases
case DXGI_FORMAT_R16G16B16A16_UNORM : return 64;
case DXGI_FORMAT_R32G32B32A32_FLOAT : return 128;
default: return -1;
}
}
Related
Take the following non-null safe Dart code:
static String appBarShiftTitleString(int fromEpochSeconds) {
String monthWord;
String dayWord;
DateTime dt = DateTime.fromMillisecondsSinceEpoch(fromEpochSeconds * 1000);
switch (dt.month) {
case 1:
monthWord = "Jan";
break;
case 2:
monthWord = "Feb";
break;
case 3:
monthWord = "Mar";
break;
case 4:
monthWord = "Apr";
break;
case 5:
monthWord = "May";
break;
case 6:
monthWord = "Jun";
break;
case 7:
monthWord = "Jul";
break;
case 8:
monthWord = "Aug";
break;
case 9:
monthWord = "Sep";
break;
case 10:
monthWord = "Oct";
break;
case 11:
monthWord = "Nov";
break;
case 12:
monthWord = "Dec";
break;
}
switch (dt.weekday) {
case 1:
dayWord = "Mon";
break;
case 2:
dayWord = "Tue";
break;
case 3:
dayWord = "Wed";
break;
case 4:
dayWord = "Thu";
break;
case 5:
dayWord = "Fri";
break;
case 6:
dayWord = "Sat";
break;
case 7:
dayWord = "Sun";
break;
}
return dayWord + ' ' + monthWord + ' ' + dt.day.toString();
}
Android Studio is saying, "The non-nullable local variable 'dayWord' must be assigned before it can be used."
I understand the error and have discovered that I can simply modify the first two lines of the method like this:
String monthWord = "error!";
String dayWord = "error!";
This way, I satisfy the language rules, and it will be plainly obvious if we reach what ought to be an impossible situation of the variable not having been assigned.
This seems hacky though... so in these types of scenarios, what is the elegant and proper way to convert this code to null safety, and if there are multiple ways, then what are the pros and cons?
In general, you have a few options:
1. Initialize the variable to some non-null sentinel value and assert later:
String monthWord = '';
// ...
switch (dt.month) {
// ...
}
assert(monthWord.isNotEmpty);
This will cause debug builds to throw AssertionError at runtime if you neglect to handle a case for it in the switch.
2. Make the variable nullable and use the null assertion operator:
String? monthWord;
// ...
switch (dt.month) {
// ...
}
monthWord!;
// Since `monthWord` is a local variable, it will now be promoted to a
// non-nullable `String` type.
This will throw a TypeError in all build types if you neglect to set the variable to a non-null value.
3. Make the variable late
Declaring variables as late states that you promise that the variables will be initialized before they are ever read. The compiler will generate runtime checks that verify that the variable is initialized when you try to access it. This will throw a LateInitializationError in all build types if you neglect to set the variable.
4. Add a default case that throws
If all of your cases set a local variable, adding a default case that throws allows the compiler to deduce that that variable must always be set if code after the switch statement is reached:
String monthWord; // No explicit initialization required!
// ...
switch (dt.month) {
case 1:
monthWord = "Jan";
break;
// ... etc. ...
default:
throw AssertionError('Unhandled case: ${dt.month}');
}
// The compiler now can deduce that `monthWord` is guaranteed to be
// initialized.
(Note that you should not add a default case for this purpose if you're using a switch statement on an enum type. For enums, the compiler and analyzer can determine if your cases are exhaustive and will generate analysis warnings if you accidentally omit any cases.)
As for which approach to use, it's mostly a matter of preference. They're all mostly equivalent in that they'll result in runtime errors. I personally would choose #1 (assert) or #4 (default case) to avoid unnecessary checks in release builds.
In your particular example, I also would just use DateTime.month and DateTime.day as indices into Lists of the month and day names respectively:
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
assert(months.length == 12);
assert(days.length == 7);
var monthWord = months[dt.month - 1];
var dayWord = days [dt.day - 1];
I need to define an age range in the case clause of the switch statement where the first case should be a number between 1 to 17 for the function to print " you are underage" and other case statements. Here is what I am trying to do:
import'dart:io';
void main(){
print ("Enter your age: ");
int age = int.parse(stdin.readLineSync());
switch (age){
case underage <=17:
print ("You are not allowed to enter");
break;
case ofage >=18 && ofage <=35:
print ("You are eligible to enter");
break;
case mature >35 && mature <= 55:
print ("welcome");
break;
default:
print ("You must go to RSL Club");
}
}
But this is not working. Please tell me how to define this range within the case clause or and other sub function under the case clause.
Many thanks in advance.
It's not really possible. The Dart switch statement's case clauses can only be single values which are compared with the switched-on value by equality.
The only way you can make this work with a switch case is using:
switch (age) {
case 0:
case 1:
case 2:
...
case 17:
print ("You are not allowed to enter");
break;
case 18:
case 19:
...
case 35:
print ("You are eligible to enter");
break;
case 36:
.. etc ..
Not really viable.
Just use if statements:
if (age < 18) {
print("You are not allowed to enter");
} else if (age <= 35) {
print("You are eligible to enter");
} else if (age <= 55) {
print("welcome");
} else {
print ("You must go to RSL Club");
}
I am working on a feature to read HKWorkout samples from the Health app. I'd like to display a description string to the user that tells them what the workout was. The only property I can see that might indicate to the user what type of activity type the sample represents is the workoutActivityType property. How am I supposed to convert the HKWorkoutActivityType to a user friendly string? Am I missing something, or is there a better way of getting a description of an HKWorkout sample?
public extension HKWorkoutActivityType {
/*
Simple mapping of available workout types to a human readable name.
*/
var name: String {
switch self {
case .americanFootball: return "American Football"
case .archery: return "Archery"
case .australianFootball: return "Australian Football"
case .badminton: return "Badminton"
case .baseball: return "Baseball"
case .basketball: return "Basketball"
case .bowling: return "Bowling"
case .boxing: return "Boxing"
case .climbing: return "Climbing"
case .crossTraining: return "Cross Training"
case .curling: return "Curling"
case .cycling: return "Cycling"
case .dance: return "Dance"
case .danceInspiredTraining: return "Dance Inspired Training"
case .elliptical: return "Elliptical"
case .equestrianSports: return "Equestrian Sports"
case .fencing: return "Fencing"
case .fishing: return "Fishing"
case .functionalStrengthTraining: return "Functional Strength Training"
case .golf: return "Golf"
case .gymnastics: return "Gymnastics"
case .handball: return "Handball"
case .hiking: return "Hiking"
case .hockey: return "Hockey"
case .hunting: return "Hunting"
case .lacrosse: return "Lacrosse"
case .martialArts: return "Martial Arts"
case .mindAndBody: return "Mind and Body"
case .mixedMetabolicCardioTraining: return "Mixed Metabolic Cardio Training"
case .paddleSports: return "Paddle Sports"
case .play: return "Play"
case .preparationAndRecovery: return "Preparation and Recovery"
case .racquetball: return "Racquetball"
case .rowing: return "Rowing"
case .rugby: return "Rugby"
case .running: return "Running"
case .sailing: return "Sailing"
case .skatingSports: return "Skating Sports"
case .snowSports: return "Snow Sports"
case .soccer: return "Soccer"
case .softball: return "Softball"
case .squash: return "Squash"
case .stairClimbing: return "Stair Climbing"
case .surfingSports: return "Surfing Sports"
case .swimming: return "Swimming"
case .tableTennis: return "Table Tennis"
case .tennis: return "Tennis"
case .trackAndField: return "Track and Field"
case .traditionalStrengthTraining: return "Traditional Strength Training"
case .volleyball: return "Volleyball"
case .walking: return "Walking"
case .waterFitness: return "Water Fitness"
case .waterPolo: return "Water Polo"
case .waterSports: return "Water Sports"
case .wrestling: return "Wrestling"
case .yoga: return "Yoga"
// iOS 10
case .barre: return "Barre"
case .coreTraining: return "Core Training"
case .crossCountrySkiing: return "Cross Country Skiing"
case .downhillSkiing: return "Downhill Skiing"
case .flexibility: return "Flexibility"
case .highIntensityIntervalTraining: return "High Intensity Interval Training"
case .jumpRope: return "Jump Rope"
case .kickboxing: return "Kickboxing"
case .pilates: return "Pilates"
case .snowboarding: return "Snowboarding"
case .stairs: return "Stairs"
case .stepTraining: return "Step Training"
case .wheelchairWalkPace: return "Wheelchair Walk Pace"
case .wheelchairRunPace: return "Wheelchair Run Pace"
// iOS 11
case .taiChi: return "Tai Chi"
case .mixedCardio: return "Mixed Cardio"
case .handCycling: return "Hand Cycling"
// iOS 13
case .discSports: return "Disc Sports"
case .fitnessGaming: return "Fitness Gaming"
// Catch-all
default: return "Other"
}
}
}
Source : https://github.com/georgegreenoflondon/HKWorkoutActivityType-Descriptions/.
HealthKit does not have an API for localizing HKWorkoutActivityType values. You need to implement your own mapping.
i have code like this
switch thing {
case thisThing:
do thing #1
do thing #2
case thatThing:
do thing #2
do thing #3
case anotherThing:
do thing #4
default:
default
}
So, EVERY case has something that ONLY IT does. Some cases also do the same things as one or more other cases.
Is there a way to accomplish this if I don't want any repetitive code?
OR, is there a much more efficient way of doing this without switch statements at all?? I mean, I could, for example, use if statements, but like switch statements, I can't think of a way to accomplish what I want without using repetitive code.
also, this example might be more clear than the above
myFavoriteNumbers = []
myLeastFavoriteNumbers = []
switch myNumber {
case 1:
print("my number is number 1") // do this only for case 1
myFavoriteNumbers += [1] // do this for case 1 and case 2
case 2:
print("this is number 2") // do this only for case 2
myFavoriteNumbers += [2] // do this for case 1 and case 2
case 3:
print("I don't like number 3") // do this only for case 3
myLeastFavoriteNumbers += [3] // do this for case 3 and case 4
case 4:
print("Number Four") // do this only for case 4
myLeastFavoriteNumbers += [4] // do this for case 3 and case 4
default:
print("Default")
}
You can use an initial separate pattern matching statement (comparable to a single case independent from the switch statement) that covers the actions that are unique for any (valid) number, and let the switch statement follow with cases that handle actions that are common for several numbers. With this you separate the unique and common logic action, where the latter is simply implemented as usual cases for any pattern matching switch implementation.
E.g., for your example
var myFavoriteNumbers: [Int] = []
var myLeastFavoriteNumbers: [Int] = []
let myNumberDescriptions = ["my number is number 1",
"this is number 2", "I don't like number 3", "Number Four"]
let myNumber = 1
/* unique action:
perform a unique action (given a valid number)
and thereafter proceed to common cases */
if 1...myNumberDescriptions.count ~= myNumber {
print(myNumberDescriptions[myNumber-1])
}
/* common cases */
switch myNumber {
/* common case: is a favourite number */
case 1...2: myFavoriteNumbers += [myNumber]
/* common case: is a least favourite number */
case 3...4: myLeastFavoriteNumbers += [myNumber]
default:
print("Default")
}
In case the action that is unique to any number is more complex, use the same approach as above, but use more advanced logic (e.g. an event handler) for the unique action "case".
You could nest switch statements that switch on the same value, like this:
switch myNumber {
case 1...2:
myFavoriteNumbers += [myNumber] // do this for case 1 and case 2
switch myNumber {
case 1:
print("my number is number 1") // do this only for case 1
default:
print("this is number 2") // do this only for case 2
}
case 3...4:
myLeastFavoriteNumbers += [myNumber] // do this for case 3 and case 4
switch myNumber {
case 3:
print("I don't like number 3") // do this only for case 3
default:
print("Number Four") // do this only for case 4
}
default:
print("Default")
}
Not the most elegant bit of code you'll ever see, but it achieves what you want to achieve without the repetition.
Fallthrough comes to mind as an obvious solution, but as somebody here already said it does not work in a way that would be helpful.
I don't have any silver bullet for you but I think I would go about this in such a way:
create one switch statement which only covers separate logic
create a second switch statement which combines common logic
switch thing {
case thisThing:
do thing #1
case thatThing:
do thing #4
case anotherThing:
do thing #5
default: ()
}
switch thing {
case thisThing, thatThing:
do thing #2
default: ()
}
It would work when your logic does not depend on the order of function calls (which it should not, if it does it may be a sign to improve your code design). To me it looks clean, however it's still not ideal..
In Swift, I need to make a switch like this:
switch char {
case "+": statement 1; statement 3
case "-": statement 2; statement 3
default: statement 3
}
However, I don't want to copy the statement 3, because it is actually quite long, so I'm looking for an alternative way (if it exists) to somehow make the switch check every case condition, and execute the default too.
Repeated code? Good candidate for a local function:
func statement3() {
// ... lots of stuff here ...
}
switch char {
case "+": statement 1; statement3()
case "-": statement 2; statement3()
default: statement3()
}
But if you really want to do statement3 in every case, then just take it out of the switch statement altogether:
switch char {
case "+": statement 1
case "-": statement 2
default: break
}
statement 3
The only way you can fallthrough a case and skip over the next one to get you to default is to retest the condition:
switch char {
case "+": statement 1; fallthrough
case "-": if char == "-" { statement 2 }; fallthrough
default: statement 3
}
which at the end of the day, let's be honest, looks awesomely frugly. I suggest you replace your long statements by function calls and keep the control flow you gave above.