
Advertisement

Content count
2414 
Joined

Last visited
Content Type
Profiles
Articles and Tutorials
News
Contractors
Columns
Podcasts
Games Industry Event Coverage
Gallery
Forums
Calendar
Blogs
Store
GameDev Links
Projects
Developers
Everything posted by Sirisian

Looking for good fast geometry compression for streaming!
Sirisian replied to fredrum's topic in Graphics and GPU Programming
This video contains a rough overview of how Microsoft does it. There are no complete libraries for this as far as I'm aware. It's possible there are papers though on each individual technique, but the process is essentially a pipeline of different point cloud and mesh algorithms. (This problem seems extremely complex by the way when it comes to creating keyframes and delta frames. Microsoft might have broken new ground when performing this research). 
How do I keep track of nearby objects?
Sirisian replied to Acar's topic in Networking and Multiplayer
Would this happen to be a normal uniform grid? I wrote a blog article years ago that covered the grid and spatial hashing methods. Might compare the data structures I use against yours. A big picture idea of interest management is that you don't have to run it in realtime. As Frob mentioned loose variations will often be used that exploit this. If designed correctly you can update entities in cells, quadtrees, etc like once per second then query and build the list of nearby entities every 2 seconds or stagger updates across many ticks. This can get kind of complex, but in the end you can end up with a system that supports thousands of entities and scales. (Overkill usually). 
Speaking of differences since I saw someone else online ask it. Can Vulkan do Rasterizer Order Views?

https://github.com/KhronosGroup/SPIRVLLVM https://github.com/google/shaderc Not aware of any others. I'm sure someone is writing an HLSL to SpirV though, but I haven't seen one yet.

https://github.com/SaschaWillems/Vulkan < More examples in case people missed them.

Someone just brought this to my attention: https://github.com/nvpropipeline/vkcpp Very simple to use C++ conversion. Should help with learning the API.

Not sure if anyone else was planning to use Skia for text rendering, but they confirmed they have a Vulkan backend in the works. Kind of surprised since I thought I'd be waiting months or have to write my own backend.

This should be fun. The quick reference makes it look so easy too. (Looks like for D3D12 users they'll have no trouble jumping over).

From an image processing standpoint you should be able to use a gradient technique. https://en.wikipedia.org/wiki/Image_gradient I'd use a 3x3 kernel to start with and maybe combine a larger kernel to generate a gradient map. Post process the gradient to smooth it then apply the changes to the grayscale image. Using this you can even increase the resolution.

Calculate time t along a 2D cubic bezier equal to a given tangent vector
Sirisian posted a topic in Math and Physics
I asked this over on stackoverflow, but I'm not sure it'll be answered there. I have a cubic bezier defined by four points. I need to find the time t along the cubic bezier where the tangent is equal to a given vector. This problem is not as straightforward as it may seem on first glance. I'll explain the basic math first for how I approached it so you can find flaws and possibly a better solution. A 2D cubic bezier and its tangent can be defined by these equations. Specifically the tangent: T(t) = 3(1t)^2 * P0 + 3(1t)^2 * P1  6t(1t) * P1  3t^2 * P2 + 6t(1t) * P2 + 3t^2 * P3 And expanded for a 2D vector: T_x(t) = 3(1t)^2 * x0 + 3(1t)^2 * x1  6t(1t) * x1  3t^2 * x2 + 6t(1t) * x2 + 3t^2 * x3 T_y(t) = 3(1t)^2 * y0 + 3(1t)^2 * y1  6t(1t) * y1  3t^2 * y2 + 6t(1t) * y2 + 3t^2 * y3 Then we also have a vector (x, y) representing the tangent we want to find the time t for. These are simple quadratic equations so we just need an equation to solve. We can take the cross product (vx0 * vy1  vy0 * vx1) between the two and solve for 0. This would find when the tangent of the cubic bezier is equal to our given tangent vector and we'd solve for t. (I don't care if the vector is opposite the tangent so if our vector is (1, 0) then it would also look for (1, 0)). In Mathematica solving for t with this cross product approach would look like this: Solve[(3(1t)^2*x0+3(1t)^2*x16t(1t)*x13t^2*x2+6t(1t)*x2+3t^2*x3)*y(3(1t)^2*y0+3(1t)^2*y16t(1t)*y13t^2*y2+6t(1t)*y2+3t^2*y3)*x==0,t,Reals] Mathematica would then output: {{t>ConditionalExpression[(x0 y2 x1 y+x2 yx y0+2 x y1x y2)/(x0 y3 x1 y+3 x2 yx3 yx y0+3 x y13 x y2+x y3)\[Sqrt]((x1^2 y^2x0 x2 y^2x1 x2 y^2+x2^2 y^2+x0 x3 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x0 y y2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2x x0 y y3+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x0 y3 x1 y+3 x2 yx3 yx y0+3 x y13 x y2+x y3)^2),(x>(x2 yx3 y)/(y2y3)&&x0>(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y>0&&y2>y3)(x<(x2 yx3 y)/(y2y3)&&x0<(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y>0&&y2>y3)(x<(x2 yx3 y)/(y2y3)&&x0<(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y<0&&y2<y3)(x<(x2 yx3 y)/(y2y3)&&y<0&&x0>(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y2>y3)(x<(x2 yx3 y)/(y2y3)&&y2<y3&&x0>(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y>0)(x0<(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y<0&&x>(x2 yx3 y)/(y2y3)&&y2>y3)(x0<(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y2<y3&&x>(x2 yx3 y)/(y2y3)&&y>0)(y<0&&y2<y3&&x>(x2 yx3 y)/(y2y3)&&x0>(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3))]}, {t>ConditionalExpression[(x0 y2 x1 y+x2 yx y0+2 x y1x y2)/(x0 y3 x1 y+3 x2 yx3 yx y0+3 x y13 x y2+x y3)+\[Sqrt]((x1^2 y^2x0 x2 y^2x1 x2 y^2+x2^2 y^2+x0 x3 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x0 y y2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2x x0 y y3+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x0 y3 x1 y+3 x2 yx3 yx y0+3 x y13 x y2+x y3)^2),(x>(x2 yx3 y)/(y2y3)&&x0>(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y>0&&y2>y3)(x<(x2 yx3 y)/(y2y3)&&x0<(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y>0&&y2>y3)(x<(x2 yx3 y)/(y2y3)&&x0<(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y<0&&y2<y3)(x<(x2 yx3 y)/(y2y3)&&y<0&&x0>(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y2>y3)(x<(x2 yx3 y)/(y2y3)&&y2<y3&&x0>(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y>0)(x0<(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y<0&&x>(x2 yx3 y)/(y2y3)&&y2>y3)(x0<(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3)&&y2<y3&&x>(x2 yx3 y)/(y2y3)&&y>0)(y<0&&y2<y3&&x>(x2 yx3 y)/(y2y3)&&x0>(x1^2 y^2x1 x2 y^2+x2^2 y^2x1 x3 y^2+x x2 y y0x x3 y y02 x x1 y y1+x x2 y y1+x x3 y y1+x^2 y1^2+x x1 y y22 x x2 y y2x^2 y0 y2x^2 y1 y2+x^2 y2^2+x x1 y y3+x^2 y0 y3x^2 y1 y3)/(x2 y^2x3 y^2x y y2+x y y3))]}} Here's an image that's easier to see. That said most of those cases have duplicate variables so it's much simpler than it looks. (Both condition cases are identical and the solutions are a positive or negative case in the equation since it solved a quadratic equation). In code form this is easy to see: var temp1 = (tx2  tx3) / (y2  y3); var temp2 = (tx1 * tx1 + tx2 * tx2 + tx2 * (ty0 + ty1  2 * ty2) + tx1 * (tx2  tx3  2 * ty1 + ty2 + ty3) + tx3 * (ty1  ty0) + ty1 * ty1  ty0 * ty2 + ty2 * ty2 + ty0 * ty3  ty1 * (ty2 + ty3)) / (tangent.y * (tx2  tx3  ty2 + ty3)); console.log ('Temp1: ', temp1, ' Temp2: ', temp2); if ( tangent.x < temp1 && ( tangent.y < 0 && ( x0 < temp2 && y2 < y3  x0 > temp2 && y2 > y3 )  tangent.y > 0 && ( x0 < temp2 && y2 > y3  x0 > temp2 && y2 < y3 ) )  tangent.x > temp1 && ( tangent.y < 0 && ( x0 < temp2 && y2 > y3  x0 > temp2 && y2 < y3 )  tangent.y > 0 && ( x0 < temp2 && y2 < y3  x0 > temp2 && y2 > y3 ) ) ) { var tx0ty0 = tx0  ty0; var ty1tx1 = ty1  tx1; var tx2ty2 = tx2  ty2; var temp6 = 2 * (tx0ty0 + tx2ty2) + 4 * ty1tx1; var temp5 = tx0ty0 + 3 * (tx2ty2 + ty1tx1) + ty3  tx3; var temp7 = temp6 * temp6  4 * (tx0ty0 + ty1tx1) * temp5; var temp3 = Math.sqrt(temp7); var temp4 = 2 * temp5; var t1 = (temp6  temp3) / temp4; var t2 = (temp6 + temp3) / temp4; } So what we have is two possible times as we'd expect since the problem is quadratic. Here's an interactive example in JS. That example uses a hardcoded tangent vector of (0.707, 0.707). (So a vector pointing down and to the right in that coordinate system). There are problems though with the above code. Even correcting for floating point errors in the inequalities and square root calculations there are cases that aren't well defined. Like when y2  y3 is 0 resulting in a division by zero case. There are subtleties to this also like in certain cases temp4 will have valid results that are very close to zero either producing the correct result or due to floating point issues generating a value for t1 and t2 much larger than expected. I've noticed this specifically in the cases where t1 or t2 are 0.5. Was thinking that flipping it across the the diagonal and solving again might solve some edge cases, but I'm just not confident on that approach. What I'd like is a tried and tested approach, possibly with a code example, or another way to tackle this without weird edge cases. 
Calculate time t along a 2D cubic bezier equal to a given tangent vector
Sirisian replied to Sirisian's topic in Math and Physics
I should have been more clear. I can probably write an iterative solution, but I'm more concerned with a closed form solution. (Since I've shown a partial solution can be calculated already for most cases). edit: Someone solved it on stackoverflow. Interesting. 
This seems strange. Wouldn't it be easier as a source file than embedding it into the driver thus making the driver harder to maintain? I assume someone will release one later though.

Developing an Ocean Shader for Unreal Engine 4
Sirisian replied to Theokoles's topic in Graphics and GPU Programming
The surface in yours looks like a large ocean of jello. The primary reason for this is you stretch and compress the whole mesh even the finest details. From watching videos of oceans waves the high noise and slow moving froth stay in place and move much less than the low frequency waves and crests. When watching videos it's like you start with a large taunt blanket then you have high frequency noise that moves very little in relation to the lower frequency waves. As you add lower frequencies of waves the movements go up and they affect each other more. Also low frequency waves crest. The lower the frequency (larger) the wave the more foam. You lose a lot of detail without this. Also for more realistic rendering (which adds a lot to the overall effect) you might want to render your objects first to a texture and extract a depth map. Then use that when rendering the water and take the difference between the depth values. Using something like beerlambert for the depth based transparency would add a lot. (I'm sure there's a paper with a more accurate volumetric transparency though for the water). 
This should probably be in the Multiplayer and Networking section. There are a few ways to handle what you're describing. Assuming you have a hash grid with uniform cell size then you just need to use the player's current camera on the server to collect all the entities in range. That just requires iterating through the cells and performing a lookup in the hash grid. Then for all the cells that exist in the hash grid union the entities into a list. This list represents all the entities the client can see. I have a tutorial on spatial partitioning and the queries here. That said the basic query function would look like this in C#: public HashSet<IGridEntity> Query(AxisAlignedBoundaryBox aabb) { var entities = new HashSet<IGridEntity>(); var startX = (int)(aabb.MinX / CellSize); var endX = (int)(aabb.MaxX / CellSize); var startY = (int)(aabb.MinY / CellSize); var endY = (int)(aabb.MaxY / CellSize); for (var x = startX; x <= endX; ++x) { for (var y = startY; y <= endY; ++y) { Cell cell; if (grid.TryGetValue(y * dimensions + x, out cell)) { entities.UnionWith(cell.Entities); } } } return entities; } Now once you have all the entities you have to tell the player about them. In the past I've advocated using a full and delta state pattern. That is for every client you store an array of all the entities you've told the client about and then on every message after that you simply tell them what's changed. If you do that then you'll have an array that's empty when the client connects. We can refer to this array as the "known entities" array. Depending on how you're building packets you'd want to add all the information about the new entities that aren't in the array (so that the client can recreate it). This would include things like the entity type. You're right that you'll want to give all the entities a unique id. You'll use this id to refer to the client entity later. If the entity is already known by the client (it's in the known entities array) then you just need to send a delta packet with things that have changed, like position. You can use bools to track changed items in the entity then after sending data to all the clients just set the bool to false. That's all there is to it. Every tick of the server query for the entities in the camera then check the known entities and either add new entity data to the packet or write a delta entity data. The client has its own array of known entities so if it receives an entity id it's never seen it knows it needs to deserialize the full state and if it already knows about the entity then it'll deserialize a delta for the entity. The two tutorials I linked go into things a lot more including how to forget entities. There are a lot of optimizations, but this is a fairly simple technique especially for a lockstep game. (It forms the basis though for a lot of technique for drastically reducing bandwidth though).

In regards to WebSockets I personally wouldn't bother with socket.io. You can just use the ws module for games. Falling back isn't necessary anymore for any browser or device. (Nor for a game is it really worth it).

I've always found the CSS documentation on MDN to be a nice overview of timing functions: https://developer.mozilla.org/enUS/docs/Web/CSS/timingfunction Also check this out: http://www.gdcvault.com/play/1020583/AnimationBootcampAnIndieApproach (It starts at movement continued with a full animation system defined by curves)

Direct3D 12 documentation is now public
Sirisian replied to Promit's topic in Graphics and GPU Programming
Yeah that's how I kind of figured and set it up my code dump above. Specifically I did: hr = mD3D11On12Device>CreateWrappedResource(mTextTexture.Get(), &mD3D11TextureFlags, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, __uuidof(ID3D11Resource), (void**)mD3D11Texture.GetAddressOf()); then ID3D11Resource* resourcesToAcquire[] = { mD3D11Texture.Get() }; mD3D11On12Device>AcquireWrappedResources(resourcesToAcquire, ARRAYSIZE(resourcesToAcquire)); // SetTarget BeginDraw EndDraw mD3D11On12Device>ReleaseWrappedResources(resourcesToAcquire, ARRAYSIZE(resourcesToAcquire)); I use it in an SRV thus the out state is pixel shader resource. That does clear up any doubts I had about the usage. I think I need to find someone with very indepth knowledge to look at the code to find the specific issue. I've switched gears and am learning other D3D12 stuff to see if maybe I learn something relevant to help. 
Direct3D 12 documentation is now public
Sirisian replied to Promit's topic in Graphics and GPU Programming
I've done about as much as I can to simplify my code examples for someone else to help. "D3D12DirectWrite.zip" has an implementation that I believe should be valid. All it does is create a ID3D12Resource and then uses it as a render target that D2D and DirectWrite to render to. It calls Render() one time to render a single frame. D2D never renders to the texture though and D3D12 renders a black texture. My current issues are in understanding ID3D11On12Device's CreateWrappedResource method. It has an "InState" and "OutState", but it's unclear to me how they should be set. They AcquireWrappedResources and ReleaseWrappedResources also have no clear usages explained other than they seem mandatory? I assume you have to acquire the texture then render then release it when you're done, but it's not clear when this needs to be done in my code. The last piece I'm confused about are if D3D12 has to do anything when working with D2D. D3D11On12CreateDevice accepts a ID3D12CommandQueue. I'm assuming it doesn't require D3D12 to do anything and that D2D will set up its own command list internally and submit it to the command queue and execute it in D2D's EndDraw method. I can't find any confirmation about this though. I've attached another example which I do not understand at all. "D3D12DirectWriteDrawsText.zip" is a program that draws text. I was copying code around and suddenly it started rendering. It's so odd though. It only renders after a few frames though. If you change the code to call "Render();" just once it renders a black square. I assume whatever it's doing is very undefined, but it shows that somehow, someway, that D2D and DirectWrite can be made to work with D3D12. I just can't find the right way. What I want is essentially contained operations. SetupEverything(); RenderTextToTexture(); // D2D and DirectWrite have completely finished rendering to a texture Render(); // Draws a single frame with the texture rendered. If someone can look at the code I'd appreciate it. I have very little DirectX experience so it's possible I'm doing something silly and unrelated wrong. Or if someone can find someone at Microsoft to look at it and write a real example that would be nice since I'm not sure if what I'm seeing is a bug. I've spent way too long on this. 
Direct3D 12 documentation is now public
Sirisian replied to Promit's topic in Graphics and GPU Programming
Is the VS graphics analyzer supposed to work right now? I can run the diagnostics tools and take frame screenshots, but if I try to view the frames it opens the analyzer and then a window displays "Visual Studio Graphics Analyzer has stopped working". Is there any information on when this feature will be available/fixed? Ah VS RC has a working graphics analyzer. Ooh, I got text to render. I think I figured out my bug finally! Graphics analyzer crashes though if I try to take a picture of the frame. Probably doing something wrong still though. More investigation is needed. 
Direct3D 12 documentation is now public
Sirisian replied to Promit's topic in Graphics and GPU Programming
Okay been noticing something. Is AcquireWrappedResources and ReleaseWrappedResources actually implemented? The documentation isn't very clear on if I'm using them right. https://msdn.microsoft.com/enus/library/dn913197%28v=vs.85%29.aspx I think I'm using it right. You acquire the D3D11Resource then render and it's like rendering to the D3D12Resource? Doesn't seem to matter though. It's like the two functions do absolutely nothing currently since the D3D12Resource is still black. It's almost like when you call CreateWrappedResource it gives you a new separate resource that doesn't affect the D3D12 resource. If anyone has access to any documentation or secret information they could hint at I'd be really grateful. I've tried everything I could think of. 
Direct3D 12 documentation is now public
Sirisian replied to Promit's topic in Graphics and GPU Programming
Maybe someone here can see something simple I'm missing or forgot to do. I'm still working on getting D2D/DirectWrite to write text to a D3D12 resource. I've removed the error handling to make this more compact: First I created the D3D12 resource. A simple 512x512 2D texture. I set the D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET flag so it can be used correctly with ID3D11On12 later without defining the flag at the CreateWrappedResource step. (I've tried both ways. You can see the flags commented out). D3D12_RESOURCE_DESC mTextTextureDesc; ZeroMemory(&mTextTextureDesc, sizeof(mTextTextureDesc)); mTextTextureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; mTextTextureDesc.Width = 512; mTextTextureDesc.Height = 512; mTextTextureDesc.MipLevels = 1; mTextTextureDesc.DepthOrArraySize = 1; mTextTextureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; mTextTextureDesc.SampleDesc.Count = 1; mTextTextureDesc.SampleDesc.Quality = 0; mTextTextureDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; mTextTextureDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; // Used in the ID3D11Device D3D12_HEAP_PROPERTIES mTextTextureHeapProperties; mTextTextureHeapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; mTextTextureHeapProperties.CreationNodeMask = 1; mTextTextureHeapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; mTextTextureHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT; mTextTextureHeapProperties.VisibleNodeMask = 1; Microsoft::WRL::ComPtr<ID3D12Resource> mTextTexture; hr = mDevice>CreateCommittedResource(&mTextTextureHeapProperties, D3D12_HEAP_FLAG_NONE, &mTextTextureDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, __uuidof(ID3D12Resource), (void**)&mTextTexture); // S_OK Since D2D/DirectWrite isn't supported by D3D12 in any simple way, the general process is to take a ID3D12Device and create a ID3D11Device then get the DXGIDevice from that. Also use the ID3D11Device to create a ID3D11On12Device. I then CreateWrappedResource to turn the ID3D12Resource into a ID3D11Resource and then turn that into a IDXGISurface then turn that into a ID2D1Bitmap1 which D2D can then render to via SetTarget. I have an issue though on the last step when converting the completely valid IDXGISurface to a ID2D1Bitmap1. const D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1 }; IUnknown* commandQueues[] = { mCommandQueue.Get() }; Microsoft::WRL::ComPtr<ID3D11Device> mD3D11Device; Microsoft::WRL::ComPtr<ID3D11DeviceContext> mD3D11DeviceContext; hr = D3D11On12CreateDevice(mDevice.Get(), D3D11_CREATE_DEVICE_SINGLETHREADED  D3D11_CREATE_DEVICE_BGRA_SUPPORT, featureLevels, ARRAYSIZE(featureLevels), commandQueues, 1, 1, mD3D11Device.GetAddressOf(), mD3D11DeviceContext.GetAddressOf(), nullptr); // S_OK Microsoft::WRL::ComPtr<ID3D11On12Device> mD3D11On12Device; hr = mD3D11Device.As(&mD3D11On12Device);// S_OK // Get the underlying DXGI device of the Direct3D device. Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice; hr = mD3D11Device.As(&dxgiDevice); // S_OK // Create the Direct2D device object and a corresponding context. Microsoft::WRL::ComPtr<ID2D1Device1> mD2DDevice; hr = mD2DFactory>CreateDevice(dxgiDevice.Get(), mD2DDevice.GetAddressOf()); // S_OK Microsoft::WRL::ComPtr<ID2D1DeviceContext1> mD2DContext; hr = mD2DDevice>CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &mD2DContext);// S_OK // Set the text texture's usage so it can be rendered to setResourceBarrier(mCommandList.Get(), mTextTexture.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_RENDER_TARGET); Microsoft::WRL::ComPtr<ID3D11Resource> mD3D11Texture; D3D11_RESOURCE_FLAGS mD3D11TextureFlags; ZeroMemory(&mD3D11TextureFlags, sizeof(mD3D11TextureFlags)); // mD3D11TextureFlags.BindFlags = D3D11_BIND_SHADER_RESOURCE  D3D11_BIND_RENDER_TARGET hr = mD3D11On12Device>CreateWrappedResource(mTextTexture.Get(), &mD3D11TextureFlags, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET, __uuidof(ID3D11Resource), (void**)mD3D11Texture.GetAddressOf());// S_OK ID3D11Resource* resourcesToAcquire[] = { mD3D11Texture.Get() }; mD3D11On12Device>AcquireWrappedResources(resourcesToAcquire, ARRAYSIZE(resourcesToAcquire)); Microsoft::WRL::ComPtr<IDXGISurface> mTextTextureDXGISurface; hr = mD3D11Texture.As(&mTextTextureDXGISurface); // S_OK const float dxgiDpi = 96.0f; mD2DContext>SetDpi(dxgiDpi, dxgiDpi); DXGI_SURFACE_DESC desc; mTextTextureDXGISurface>GetDesc(&desc); // Just as a test this returns 512x512 with the format DXGI_FORMAT_B8G8R8A8_UNORM D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET  D2D1_BITMAP_OPTIONS_CANNOT_DRAW, D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED), dxgiDpi, dxgiDpi); Microsoft::WRL::ComPtr<ID2D1Bitmap1> mTextTextureD2DBitmap; hr = mD2DContext>CreateBitmapFromDxgiSurface(mTextTextureDXGISurface.Get(), &bitmapProperties, mTextTextureD2DBitmap.GetAddressOf()); // One or more arguments are invalid Essentially everything is fine (as shown by the GetDesc) until it attempts to turn the IDXGISurface into a ID2D1Bitmap1. In the debug I get: D2D DEBUG WARNING  The IDXGISurface passed to this API has an invalid combination of usage and bind flags. The resulting D2D bitmap will still be created but it will be unusable. D2D DEBUG ERROR  The bitmap options [0x3] must be a subset of the flags associated with the DXGI surface. Okay a few hours of toying around. I "fixed" it. No errors. Just a single warning and a rendered black square instead of a Red square with text. D3D12_RESOURCE_DESC mTextTextureDesc; ZeroMemory(&mTextTextureDesc, sizeof(mTextTextureDesc)); mTextTextureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; mTextTextureDesc.Width = 512; mTextTextureDesc.Height = 512; mTextTextureDesc.MipLevels = 1; mTextTextureDesc.DepthOrArraySize = 1; mTextTextureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; mTextTextureDesc.SampleDesc.Count = 1; mTextTextureDesc.SampleDesc.Quality = 0; mTextTextureDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; mTextTextureDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; D3D12_HEAP_PROPERTIES mTextTextureHeapProperties; mTextTextureHeapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; mTextTextureHeapProperties.CreationNodeMask = 1; mTextTextureHeapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; mTextTextureHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT; mTextTextureHeapProperties.VisibleNodeMask = 1; Microsoft::WRL::ComPtr<ID3D12Resource> mTextTexture; hr = mDevice>CreateCommittedResource(&mTextTextureHeapProperties, D3D12_HEAP_FLAG_NONE, &mTextTextureDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, __uuidof(ID3D12Resource), (void**)&mTextTexture); Essentially D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET is required and the initial state must be either set to D3D12_RESOURCE_STATE_RENDER_TARGET or changed to it before working with it. D2D1_FACTORY_OPTIONS options; ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS)); options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; Microsoft::WRL::ComPtr<ID2D1Factory2> mD2DFactory; hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory2), &options, &mD2DFactory); const D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1 }; IUnknown* commandQueues[] = { mCommandQueue.Get() }; Microsoft::WRL::ComPtr<ID3D11Device> mD3D11Device; Microsoft::WRL::ComPtr<ID3D11DeviceContext> mD3D11DeviceContext; hr = D3D11On12CreateDevice(mDevice.Get(), D3D11_CREATE_DEVICE_SINGLETHREADED  D3D11_CREATE_DEVICE_BGRA_SUPPORT, featureLevels, ARRAYSIZE(featureLevels), commandQueues, 1, 1, mD3D11Device.GetAddressOf(), mD3D11DeviceContext.GetAddressOf(), nullptr); Microsoft::WRL::ComPtr<ID3D11On12Device> mD3D11On12Device; hr = mD3D11Device.As(&mD3D11On12Device); // Get the underlying DXGI device of the Direct3D device. Microsoft::WRL::ComPtr<IDXGIDevice1> dxgiDevice; hr = mD3D11Device.As(&dxgiDevice); // Create the Direct2D device object and a corresponding context. Microsoft::WRL::ComPtr<ID2D1Device1> mD2DDevice; hr = mD2DFactory>CreateDevice(dxgiDevice.Get(), mD2DDevice.GetAddressOf()); Microsoft::WRL::ComPtr<ID2D1DeviceContext1> mD2DContext; hr = mD2DDevice>CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &mD2DContext); // Set the text texture's usage so it can be rendered to //setResourceBarrier(mCommandList.Get(), mTextTexture.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_RENDER_TARGET); Microsoft::WRL::ComPtr<ID3D11Resource> mD3D11Texture; D3D11_RESOURCE_FLAGS mD3D11TextureFlags; ZeroMemory(&mD3D11TextureFlags, sizeof(mD3D11TextureFlags)); mD3D11TextureFlags.BindFlags = D3D11_BIND_SHADER_RESOURCE  D3D11_BIND_RENDER_TARGET; hr = mD3D11On12Device>CreateWrappedResource(mTextTexture.Get(), &mD3D11TextureFlags, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, __uuidof(ID3D11Resource), (void**)mD3D11Texture.GetAddressOf()); ID3D11Resource* resourcesToAcquire[] = { mD3D11Texture.Get() }; mD3D11On12Device>AcquireWrappedResources(resourcesToAcquire, ARRAYSIZE(resourcesToAcquire)); Microsoft::WRL::ComPtr<IDXGISurface> mTextTextureDXGISurface; hr = mD3D11Texture.As(&mTextTextureDXGISurface); FLOAT dxgiDpiX, dxgiDpiY; mD2DFactory>GetDesktopDpi(&dxgiDpiX, &dxgiDpiY); mD2DContext>SetDpi(dxgiDpiX, dxgiDpiY); D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET  D2D1_BITMAP_OPTIONS_CANNOT_DRAW, D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED), dxgiDpiX, dxgiDpiY); Microsoft::WRL::ComPtr<ID2D1Bitmap1> mTextTextureD2DBitmap; DXGI_SURFACE_DESC desc; mTextTextureDXGISurface>GetDesc(&desc); hr = mD2DContext>CreateBitmapFromDxgiSurface(mTextTextureDXGISurface.Get(), &bitmapProperties, mTextTextureD2DBitmap.GetAddressOf()); mD2DContext>SetTarget(mTextTextureD2DBitmap.Get()); D2D1_SIZE_F renderTargetSize = mD2DContext>GetSize(); mD2DContext>BeginDraw(); mD2DContext>SetTransform(D2D1::Matrix3x2F::Identity()); mD2DContext>Clear(D2D1::ColorF(D2D1::ColorF::Red)); Microsoft::WRL::ComPtr<IDWriteFactory2> mDWriteFactory; hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &mDWriteFactory); Microsoft::WRL::ComPtr<IDWriteTextFormat> textFormat; hr = mDWriteFactory>CreateTextFormat(L"Verdana", nullptr, DWRITE_FONT_WEIGHT_LIGHT, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 52, L"enUS", &textFormat); // Center the text horizontally. hr = textFormat>SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING); // Center the text vertically. hr = textFormat>SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR); //pRenderTarget>SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE) Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> whiteBrush; hr = mD2DContext>CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &whiteBrush); std::wstring title = L"abcdefghijklmnopqrstuvwxyz"; mD2DContext>DrawText(title.c_str(), static_cast<UINT32>(title.length()), textFormat.Get(), D2D1::RectF(0, 0, renderTargetSize.width, renderTargetSize.height), whiteBrush.Get()); hr = mD2DContext>EndDraw(); mD3D11On12Device>ReleaseWrappedResources(resourcesToAcquire, ARRAYSIZE(resourcesToAcquire)); //setResourceBarrier(mCommandList.Get(), mTextTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); I do get a warning on EndDraw about: D3D12 WARNING: ID3D12CommandList::ClearRenderTargetView: The application did not pass any clear value to resource creation. The clear operation is typically slower as a result; but will still clear to the desired value. Not clear how to solve that. Still a black square being rendered. I must be close. Solved that. Didn't notice, but I had my CreateCommittedResource I needed to pass in a clear color value and it must match when clearing later. 
Direct3D 12 documentation is now public
Sirisian replied to Promit's topic in Graphics and GPU Programming
Yes, IDXGIDevice interfaces are no longer supported with Direct3D 12 (that's not a big secret as you found out about it!). If you look in the SDK you will find an header (and its .IDL) called "d3d11on12" and if you open it you will find what this new API is meant about: interoop between Direct3D 12 and Direct3D 11 (also not another big secret since it states in the API comments). Darn. Yeah I commented about that the other day. Got the impression that d3d11on12 was the only way, but noticed the only missing piece was the IDXGIDevice. Seemed weird to have to use a whole separate API as a workaround. I have it partly coded though. Thanks for the clarification. Actually not too bad. Just needed this I think: const const D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1 }; IUnknown* commandQueues[] = { mCommandQueue.Get() }; Microsoft::WRL::ComPtr<ID3D11Device> mD3D11Device; Microsoft::WRL::ComPtr<ID3D11DeviceContext> mD3D11DeviceContext; hr = D3D11On12CreateDevice(mDevice.Get(), D3D11_CREATE_DEVICE_SINGLETHREADED  D3D11_CREATE_DEVICE_BGRA_SUPPORT, featureLevels, ARRAYSIZE(featureLevels), commandQueues, 1, 1, mD3D11Device.GetAddressOf(), mD3D11DeviceContext.GetAddressOf(), nullptr); This returns S_OK. It works! Then also you need to do: Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice; hr = mD3D11Device.As(&dxgiDevice); // S_OK Microsoft::WRL::ComPtr<ID2D1Device1> mD2DDevice; hr = mD2DFactory>CreateDevice(dxgiDevice.Get(), mD2DDevice.GetAddressOf()); // S_OK I'll have a full example when I'm done understanding and learning. I don't want to give out bad code examples since I've never really used D3D before this point. 
Direct3D 12 documentation is now public
Sirisian replied to Promit's topic in Graphics and GPU Programming
Okay almost have DirectWrite working and Direct2D. All the code is done from what I can tell. One big issue though and I fear this is a critical bug still. You can't get a IDXGIDevice from a ID3D12Device? Microsoft::WRL::ComPtr<ID3D12Device> mDevice; hr = D3D12CreateDevice(.., D3D_DRIVER_TYPE_UNKNOWN, D3D12_CREATE_DEVICE_NONE, D3D_FEATURE_LEVEL_11_1, D3D12_SDK_VERSION, __uuidof(ID3D12Device), (void**)&mDevice); Microsoft::WRL::ComPtr<IDXGIDevice2> dxgiDevice; hr = mDevice.As(&dxgiDevice); // E_NOINTERFACE No such interface supported. As you may know the alternative code, shown in the documentaiton, when not using ComPtr is: hr = mDevice>QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice); // E_NOINTERFACE No such interface supported. This produces the same error with IDXGIDevice, IDXGIDevice1, IDXGIDevice2, or IDXGIDevice3. Since getting a valid IDXGIDevice is required to create a ID2D1Device1  using the ID2D1Factory2  it's impossible to use DirectWrite easily with D3D12 as far as I can see. Is there something simple I'm missing? Did something change with how you go from D3D12Device to IDXGIDevice2? 
Direct3D 12 documentation is now public
Sirisian replied to Promit's topic in Graphics and GPU Programming
Just so I don't waste time. What's the easiest way to use DirectWrite with D3D12? The current way that seems viable is D3D11 with Direct2D to use DirectWrite to then use ID3D1211On12Device? This seems slightly convoluted? Am I missing something obvious? 
What are your opinions on DX12/Vulkan/Mantle?
Sirisian replied to Seabolt's topic in Graphics and GPU Programming
Just saw this was posted: https://msdn.microsoft.com/enus/library/windows/desktop/dn903821%28v=vs.85%29.aspx Seems to be the D3D12 Documentation.

Advertisement