Skip navigation.

Software Development

Correcting The Future

October 2008

( Monthly archive )

GPU: Antialiased Circle Drawing (w/ screenshot)

I just got done implementing a GPU circle drawing algorithm. I only concern myself with a full circle. If you only want part of a circle, you can update the method if you'd like. You can use clipping planes or whatever else. I'm only going to describe the technique. You need to understand vertex and pixel shaders for this article. I'm am posting it for reference only.

In texture coordinates, UV are in the [0,1] range inclusive. So we don't need to work with actual pixel sizes to draw a circle within a pixel shader. Say we create a virtual texture. A virtual texture is one where you set up the texture unit, but don't give it a texture. Instead, you apply a pixel shader that will use the texture coordinates to calculate the final image. In our case, we want to convert texture coordinates to a circle.

Say we want a circle with radius of 120 pixels, we would create a virtual texture that is the next power of two of the diameter. The diameter would be 240, so the virtual texture size would have to be 256x256.

Read more...

Project V: Listing Types

I've updated my TODO list for those curious as to the status of Project V. I can now edit values for types from within the IDE. Take a look at this partial screenshot.



Just a little recap as to how types are defined in Project V. There are three kinds of entities.

1. Types
2. Modifiers
3. Instances

A type is the most powerful and flexible entity. It contains sets. In the above screenshot, you can see a type by the name of Integer. It has one set called Properties. The Properties set is special in that it defines the meaning of the type itself. You can see three of those properties: Size, Signed and Endian. As you can see, we have defined a 4 byte signed integer that is stored in little endian order. Simply use or create a type with different properties to get a different kind of integer.

The last line is MyInteger. This is a derived entity from the Integer type. Since it has a value (22), we can infer that it is an instance. So by creating an instance entity and deriving it from a specific type, we create an instance of that type. From the properties, the IDE knows that 22 takes up 4 bytes, is signed and is stored in little endian order.

To really screw with your head, consider that each of the properties are also instances and are defined exactly like MyInteger is defined. Note that the size property has a base type of Integer of which it is helping to define. In Project V, circular type definitions like this are no problem.

Here is C++ style pseudo code to explain the Size property.

class Integer
{
Properties:  // Imagine this defines a set
  Integer Size=4;
  Bool Signed=TRUE;
  Endian Endian=little;
} MyInteger = 22;


(Heck, I may allow users to create type definitions in this manner. Look at the Size property again. If Size is itself an instance, what is the size of it and what property defines it? Answer: itself!)

So far I've explained types and instances. But what about modifiers? Modifiers and instances are almost identical. While types can have many other base types, modifiers and instances can only have one direct base type. And the only difference between modifiers and instances is that a modifier will not create an instance. So you can use a modifier to override properties in base types. In fact, MyInteger is derived from the Int32 modifier which contains the properties you see in the screenshot above. And the typename of MyInteger would be Int32, NOT Integer as that is further up the hierarchy.

Here is really what's going on.

type Integer
{
Properties:  // Imagine this defines a set
  Integer Size;
  Bool Signed;
  Endian Endian;
}

modifier Int32 : Integer
{
// Override the Properties set in the Integer type
Properties(Integer):
  Size = 4;
  Signed = TRUE;
  Endian = little;
}

type Enum
{
// The Options set will contain the items of the enumeration.
Options: 
}

type Bool : Int32, Enum
{
// Override the Options set in Enum.
Options(Enum): 
  Bool FALSE = 0;
  Bool TRUE = 1;
}

type Endian : Int32, Enum
{
// Override the Options set in Enum.
Options(Enum):
  Endian little = 0;
  Endian big = 1;
}

Int32 MyInteger = 22;


So how should I show the typename of all the properties? Most property editors don't show it at all. I don't really want to widen the treeview to display this information. A rollover popup might be good. However, I'm not sure what's the best way to go. Any suggestions? Maybe I could toggle it on or off and display instances as "Int32:MyInteger". I'm still not sure.

I'll be working on connecting components together next. I'll have to display instances and its type hierarchy as well. Moreso than what's in the screenshot above. That's mostly for updating existing data structures and values.

So what should be the very first component to show itself in Project V? Addition? Or maybe a more esoteric component? And if there are suggestions for built-in components, let me know. Right now, I have this potential list (which will only work on integers to start off until I can make generic versions).

Multiplexor
Demultiplexor
Compare !=
Compare ==
Compare <=
Compare <
Compare >=
Compare >
And
Or
Xor
Not
Div (two outputs. Quotient and Remainder)
Mul
Subtraction
Addition

The multiplexor and demultiplexor are required as this is how you select where data goes. But if I didn't care about speed, I could build them out of the other components.

The Demultiplexor takes two inputs (and has two outputs although only one output is activated at a time). The first input is a boolean selector that selects what output to send the input. So there are two outputs named TRUE and FALSE which are activated depending on the state of the selector.

The Multiplexor has three inputs and one output. It again has a boolean selector and chooses either the input with the label of TRUE or FALSE depending on its state. The selected input is sent out on the output and the other value is discarded.

I'm thinking of building a swap component based on a selector instead of the multiplexor. Three inputs and two outputs. Basically two inputs are sent directly to two corresponding outputs if the selector is FALSE. If the selector is TRUE, then the inputs are swapped. That may be more useful than a multiplexor. If you don't use the second output, you can simply leave it unconnected and you have exactly the same functionality as a multiplexor.

And believe it or not, you can build anything and everything possible with that setup though I wouldn't recommend using such low level components for actual software development.

That would make a total of 16 components, many of which can be built from a subset of that same list. Actually, you only need two components to build anything you want. A NOT component and your choice of AND or OR component. You decide which one you want. In fact, you could combine them and only have ONE component (NAND or NOR). So it's not the computations that are critical. It's the ability to link those computations together. That's where the power comes from.

Project V Primitive Types

I'm not sure how to go about this or if it's even worth changing, but I thought I'd mention it. Primitive types currently come in two forms. The first kind is a built-in type like integers or floating point. The second kind is based on the first kind, but also has a secondary Enum type. This secondary Enum type has a set called Options and this is where you insert the possible options for the value of an instance.

For example, the Boolean type is derived from the Integer type as well as the Enum type. The Boolean type then inserts FALSE=0 and TRUE=1 into its Options set. So the Boolean type is 100% defined within the current type system and is NOT a built in type. Yet, it is a primitive type.

There will be a third kind of primitive type for ranges.

I wanted to have all primitive types based on the Enumeration type, but that won't really work. I don't want both the Integer type and the Boolean type to each have a secondary Enum type. IOW, I don't think it's a good idea to create one Enumeration from another. I think that would lead to messy data structures.

So, I'm wondering if all primitive types, the built-in kind and the Enumeration kind, should have a common base type to specify that it is a primitive type? I don't see a need for it. I just don't want to end up later on wishing I had reconsidered.

No current language has this anyways. So I don't think it's an issue.

Come to think of it, I don't think it's necessary to know the internals of anything. It's just a matter of what operations are allowed through components. For example, strings aren't enumerations, but are primitive types.

You can check my TODO LIST for updates. I've just added the ability to change the value of Enumerations from the GUI. This is why I like Enumerations. I can get a list of options from the Options set that is included with each Enum type and list them in the popup menu. Then you can pick which one you want.

After this, I'll add the ability to change integers. Once that's done, I'll add the ability to create new types including compound components. That should be fun. FINALLY!!! I'll be able to connect components together and actually get something to execute.

Simple Thought

I just had an extremely simple thought (insert joke here). I was looking on reddit at some examples of bad code, and well...

Let me present you with two scenarios.

1. Collosal failure for code. Pure crap.
2. No comments and cryptic variable names, but seems well organised.

Which one would you take?

Read more...

Networks

I was fixing a bug in Project V (tree traversal used with the type system) and after I was done, I decided to go look around on data flow programming. I did not really look far. As you probably know, Paul Morrison invented Flow-Based Programming. I found out his son Joe also has a blog. I ended up on an article Joe wrote about networks not being perfect.

This is an all too important point. Networks are not perfect. People get disconnected from the Internet all the time. So if the future of programming involves the use of more concurrent applications, we can't assume that every function call or every request will return with a valid response. We can't even assume that a response will arrive at all. How do we deal with this? There are three ways to handle this that I can think of. If you think of more, let me know.

1. Try and handle it locally.

This is rather simple. If you're using some external resource and it's not currently available, you can try and replicate the external scenario on the local machine or local resources that you have at your disposal. Note that although I say "local", I'm talking about any resources that are still available even if they are on other remote machines.

Read more...

Wavelets That Aren't

Ever work on a side project just for fun? This is one of my projects. In the Project V IDE (a development environment for dataflow), I decided to test out a few different algorithms. The Project V IDE is a fully 3D capable environment that can take care of all your graphical needs. So when I need to display several images, I can just drop them on the main layer. A layer is like a virtual desktop that you can scroll around.

My side project involves creating my own custom codec, but using wavelet techniques. Not only that, but I want most of the computations done on the video card. That's why Project V is so important. It takes care of all the setup for me and I can have multiple graphical applications running at the same time within Project V. Right now, it's all coded in C++, but eventually, you'll be able to do all this stuff using dataflow components. That's for another discussion though.

Why do I want to do this? It's because I want a really simple algorithm that will run even on old hardware. Why old hardware? Because it means it can be done cheaply and everyone can enjoy it's use even on legacy hardware. But it's primarily because simple algorithms would be very cheap to implement directly in hardware if it ever came to that. The newest popular codec is x264 and cannot be used on old XBOX's or old PC's. We're talking video here. It should not be computationally intensive to display a video. Just for proof, check this out where full motion video is displayed on an 8088. As an option, I'm also of the opinion that having a really high compression is fine if older boxes can uncompress them easily before viewing. IOW, you download the video like a zip file and then uncompress it before viewing. Newer hardware can view them directly. The delay would be annoying, but it's a one time deal, should be part of the download process, and people with older hardware would rather have this option than not being able to view the video at all.

Read more...

Are API's Really Better Than Memory Mapped I/O?

Full article below the fold.
Warning: Long article below.

Read more...

December 2009
S M T W T F S
November 2009January 2010
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31