From bd8276b0ea2ad33a797d705a10062b67ce49482d Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 13 Mar 2022 23:42:35 -0400 Subject: [PATCH] First pass at CreateBuffer, SetBufferData, QueueDestroyBuffer, CreateGraphicsPipeline, QueueDestroyGraphicsPipeline, DrawPrimitives, and setting default viewport/scissor rects on render passes --- src/Refresh_Driver_D3D11.c | 586 +++++++++++++++++++++++++++++++++++-- 1 file changed, 562 insertions(+), 24 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index c3075be..3a86ab0 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -158,7 +158,7 @@ static D3D11_PRIMITIVE_TOPOLOGY RefreshToD3D11_PrimitiveType[] = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP /* TRIANGLESTRIP */ }; -static D3D11_FILL_MODE RefreshToD3D11_PolygonMode[] = +static D3D11_FILL_MODE RefreshToD3D11_FillMode[] = { D3D11_FILL_SOLID, /* FILL */ D3D11_FILL_WIREFRAME, /* LINE */ @@ -289,6 +289,11 @@ typedef struct D3D11Texture }; } D3D11Texture; +typedef struct D3D11Buffer +{ + ID3D11Buffer *handle; +} D3D11Buffer; + typedef struct D3D11SwapchainData { IDXGISwapChain* swapchain; @@ -327,8 +332,32 @@ typedef struct D3D11ShaderModule size_t numEntryPoints; const spvc_entry_point *entryPoints; ID3D11DeviceChild **shaders; /* ID3D11VertexShader, ID3D11PixelShader, ID3D11ComputeShader */ + ID3D10Blob **blobs; } D3D11ShaderModule; +typedef struct D3D11GraphicsPipeline +{ + float blendConstants[4]; + + int32_t numColorAttachments; + int32_t colorAttachmentSampleCounts[MAX_COLOR_TARGET_BINDINGS]; + DXGI_FORMAT colorAttachmentFormats[MAX_COLOR_TARGET_BINDINGS]; + ID3D11BlendState *colorAttachmentBlendState; + + uint8_t hasDepthStencilAttachment; + DXGI_FORMAT depthStencilAttachmentFormat; + + D3D11_PRIMITIVE_TOPOLOGY primitiveTopology; + uint32_t stencilRef; + ID3D11DepthStencilState *depthStencilState; + ID3D11RasterizerState *rasterizerState; + ID3D11InputLayout *inputLayout; + + Refresh_MultisampleState multisampleState; + ID3D11VertexShader *vertexShader; + ID3D11PixelShader *fragmentShader; +} D3D11GraphicsPipeline; + typedef struct D3D11Renderer { ID3D11Device *device; @@ -351,7 +380,6 @@ typedef struct D3D11Renderer uint8_t debugMode; D3D_FEATURE_LEVEL featureLevel; - PFN_D3DCOMPILE D3DCompileFunc; } D3D11Renderer; @@ -693,7 +721,14 @@ static void D3D11_DrawPrimitives( uint32_t vertexParamOffset, uint32_t fragmentParamOffset ) { - NOT_IMPLEMENTED + D3D11CommandBuffer *cmdbuf = (D3D11CommandBuffer*) commandBuffer; + ID3D11DeviceContext_Draw( + cmdbuf->context, + primitiveCount * 3, /* FIXME: Needs to use a primitive lookup table! */ + vertexStart + ); + + /* FIXME: vertex/fragment param offsets */ } static void D3D11_DispatchCompute( @@ -709,6 +744,224 @@ static void D3D11_DispatchCompute( /* State Creation */ +static ID3D11BlendState* D3D11_INTERNAL_FetchBlendState( + D3D11Renderer *renderer, + uint32_t numColorAttachments, + Refresh_ColorAttachmentDescription *colorAttachments +) { + ID3D11BlendState *result; + D3D11_BLEND_DESC blendDesc; + uint32_t i; + HRESULT res; + + /* Create a new blend state. + * The spec says the driver will not create duplicate states, so there's no need to cache. + */ + SDL_zero(blendDesc); /* needed for any unused RT entries */ + + blendDesc.AlphaToCoverageEnable = FALSE; + blendDesc.IndependentBlendEnable = TRUE; + + for (i = 0; i < numColorAttachments; i += 1) + { + blendDesc.RenderTarget[i].BlendEnable = colorAttachments[i].blendState.blendEnable; + blendDesc.RenderTarget[i].BlendOp = RefreshToD3D11_BlendOp[ + colorAttachments[i].blendState.colorBlendOp + ]; + blendDesc.RenderTarget[i].BlendOpAlpha = RefreshToD3D11_BlendOp[ + colorAttachments[i].blendState.alphaBlendOp + ]; + blendDesc.RenderTarget[i].DestBlend = RefreshToD3D11_BlendFactor[ + colorAttachments[i].blendState.dstColorBlendFactor + ]; + blendDesc.RenderTarget[i].DestBlendAlpha = RefreshToD3D11_BlendFactor[ + colorAttachments[i].blendState.dstAlphaBlendFactor + ]; + blendDesc.RenderTarget[i].RenderTargetWriteMask = colorAttachments[i].blendState.colorWriteMask; + blendDesc.RenderTarget[i].SrcBlend = RefreshToD3D11_BlendFactor[ + colorAttachments[i].blendState.srcColorBlendFactor + ]; + blendDesc.RenderTarget[i].SrcBlendAlpha = RefreshToD3D11_BlendFactor[ + colorAttachments[i].blendState.srcAlphaBlendFactor + ]; + } + + res = ID3D11Device_CreateBlendState( + renderer->device, + &blendDesc, + &result + ); + ERROR_CHECK_RETURN("Could not create blend state", NULL); + + return result; +} + +static ID3D11DepthStencilState* D3D11_INTERNAL_FetchDepthStencilState( + D3D11Renderer *renderer, + Refresh_DepthStencilState depthStencilState +) { + ID3D11DepthStencilState *result; + D3D11_DEPTH_STENCIL_DESC dsDesc; + HRESULT res; + + /* Create a new depth-stencil state. + * The spec says the driver will not create duplicate states, so there's no need to cache. + */ + dsDesc.DepthEnable = depthStencilState.depthTestEnable; + dsDesc.StencilEnable = depthStencilState.stencilTestEnable; + dsDesc.DepthFunc = depthStencilState.compareOp; + dsDesc.DepthWriteMask = ( + depthStencilState.depthWriteEnable ? + D3D11_DEPTH_WRITE_MASK_ALL : + D3D11_DEPTH_WRITE_MASK_ZERO + ); + + dsDesc.BackFace.StencilFunc = depthStencilState.backStencilState.compareOp; + dsDesc.BackFace.StencilDepthFailOp = depthStencilState.backStencilState.depthFailOp; + dsDesc.BackFace.StencilFailOp = depthStencilState.backStencilState.failOp; + dsDesc.BackFace.StencilPassOp = depthStencilState.backStencilState.passOp; + + dsDesc.FrontFace.StencilFunc = depthStencilState.frontStencilState.compareOp; + dsDesc.FrontFace.StencilDepthFailOp = depthStencilState.frontStencilState.depthFailOp; + dsDesc.FrontFace.StencilFailOp = depthStencilState.frontStencilState.failOp; + dsDesc.FrontFace.StencilPassOp = depthStencilState.frontStencilState.passOp; + + /* FIXME: D3D11 doesn't have separate read/write masks for each stencil side. What should we do? */ + dsDesc.StencilReadMask = depthStencilState.backStencilState.compareMask; + dsDesc.StencilWriteMask = depthStencilState.backStencilState.writeMask; + + /* FIXME: What do we do with these? + * depthStencilState.depthBoundsTestEnable + * depthStencilState.maxDepthBounds + * depthStencilState.minDepthBounds + */ + + res = ID3D11Device_CreateDepthStencilState( + renderer->device, + &dsDesc, + &result + ); + ERROR_CHECK_RETURN("Could not create depth-stencil state", NULL); + + return result; +} + +static ID3D11RasterizerState* D3D11_INTERNAL_FetchRasterizerState( + D3D11Renderer *renderer, + Refresh_RasterizerState rasterizerState +) { + ID3D11RasterizerState *result; + D3D11_RASTERIZER_DESC rasterizerDesc; + HRESULT res; + + /* Create a new rasterizer state. + * The spec says the driver will not create duplicate states, so there's no need to cache. + */ + rasterizerDesc.AntialiasedLineEnable = FALSE; + rasterizerDesc.CullMode = RefreshToD3D11_CullMode[rasterizerState.cullMode]; + rasterizerDesc.DepthBias = (INT) rasterizerState.depthBiasConstantFactor; /* FIXME: Is this cast correct? */ + rasterizerDesc.DepthBiasClamp = rasterizerState.depthBiasClamp; + rasterizerDesc.DepthClipEnable = TRUE; /* FIXME: Do we want this...? */ + rasterizerDesc.FillMode = RefreshToD3D11_FillMode[rasterizerState.fillMode]; + rasterizerDesc.FrontCounterClockwise = (rasterizerState.frontFace == REFRESH_FRONTFACE_COUNTER_CLOCKWISE); + rasterizerDesc.MultisampleEnable = TRUE; /* only applies to MSAA render targets */ + rasterizerDesc.ScissorEnable = TRUE; + rasterizerDesc.SlopeScaledDepthBias = rasterizerState.depthBiasSlopeFactor; + + res = ID3D11Device_CreateRasterizerState( + renderer->device, + &rasterizerDesc, + &result + ); + ERROR_CHECK_RETURN("Could not create rasterizer state", NULL); + + return result; +} + +static uint32_t D3D11_INTERNAL_FindIndexOfVertexBinding( + uint32_t targetBinding, + const Refresh_VertexBinding *bindings, + uint32_t numBindings +) { + uint32_t i; + for (i = 0; i < numBindings; i += 1) + { + if (bindings[i].binding == targetBinding) + { + return i; + } + } + + Refresh_LogError("Could not find vertex binding %d!", targetBinding); + return 0; +} + +static ID3D11InputLayout* D3D11_INTERNAL_FetchInputLayout( + D3D11Renderer *renderer, + Refresh_VertexInputState inputState, + ID3D10Blob *shaderBlob +) { + ID3D11InputLayout *result = NULL; + D3D11_INPUT_ELEMENT_DESC *elementDescs; + uint32_t i, bindingIndex; + HRESULT res; + + /* Allocate an array of vertex elements */ + elementDescs = SDL_stack_alloc( + D3D11_INPUT_ELEMENT_DESC, + inputState.vertexAttributeCount + ); + + /* Create the array of input elements */ + for (i = 0; i < inputState.vertexAttributeCount; i += 1) + { + elementDescs[i].AlignedByteOffset = inputState.vertexAttributes[i].offset; + elementDescs[i].Format = RefreshToD3D11_VertexFormat[ + inputState.vertexAttributes[i].format + ]; + elementDescs[i].InputSlot = inputState.vertexAttributes[i].binding; + + bindingIndex = D3D11_INTERNAL_FindIndexOfVertexBinding( + elementDescs[i].InputSlot, + inputState.vertexBindings, + inputState.vertexBindingCount + ); + elementDescs[i].InputSlotClass = RefreshToD3D11_VertexInputRate[ + inputState.vertexBindings[bindingIndex].inputRate + ]; + /* The spec requires this to be 0 for per-vertex data */ + elementDescs[i].InstanceDataStepRate = ( + elementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA ? 1 : 0 + ); + + elementDescs[i].SemanticIndex = inputState.vertexAttributes[i].location; + elementDescs[i].SemanticName = "TEXCOORD"; + } + + res = ID3D11Device_CreateInputLayout( + renderer->device, + elementDescs, + inputState.vertexAttributeCount, + (void*) ID3D10Blob_GetBufferPointer(shaderBlob), + ID3D10Blob_GetBufferSize(shaderBlob), + &result + ); + if (FAILED(res)) + { + Refresh_LogError("Could not create input layout! Error: %X", res); + SDL_stack_free(elementDescs); + return NULL; + } + + /* FIXME: + * These are not cached by the driver! Should we cache them, or allow duplicates? + * If we have one input layout per graphics pipeline maybe that wouldn't be so bad...? + */ + + SDL_stack_free(elementDescs); + return result; +} + static Refresh_ComputePipeline* D3D11_CreateComputePipeline( Refresh_Renderer* driverData, Refresh_ComputeShaderInfo* computeShaderInfo @@ -720,7 +973,109 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( Refresh_Renderer* driverData, Refresh_GraphicsPipelineCreateInfo* pipelineCreateInfo ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11GraphicsPipeline *pipeline = (D3D11GraphicsPipeline*) SDL_malloc(sizeof(D3D11GraphicsPipeline)); + D3D11ShaderModule* vertShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->vertexShaderInfo.shaderModule; + D3D11ShaderModule* fragShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->fragmentShaderInfo.shaderModule; + int32_t vertexShaderIndex, fragmentShaderIndex; + int32_t i; + + /* Color attachments */ + pipeline->numColorAttachments = pipelineCreateInfo->attachmentInfo.colorAttachmentCount; + for (i = 0; i < pipeline->numColorAttachments; i += 1) + { + pipeline->colorAttachmentSampleCounts[i] = RefreshToD3D11_SampleCount[ + pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions[i].sampleCount + ]; + + pipeline->colorAttachmentFormats[i] = RefreshToD3D11_SurfaceFormat[ + pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions[i].format + ]; + } + + pipeline->blendConstants[0] = pipelineCreateInfo->blendConstants[0]; + pipeline->blendConstants[1] = pipelineCreateInfo->blendConstants[1]; + pipeline->blendConstants[2] = pipelineCreateInfo->blendConstants[2]; + pipeline->blendConstants[3] = pipelineCreateInfo->blendConstants[3]; + pipeline->multisampleState = pipelineCreateInfo->multisampleState; + + pipeline->colorAttachmentBlendState = D3D11_INTERNAL_FetchBlendState( + renderer, + pipelineCreateInfo->attachmentInfo.colorAttachmentCount, + pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions + ); + + /* Depth stencil */ + pipeline->hasDepthStencilAttachment = pipelineCreateInfo->attachmentInfo.hasDepthStencilAttachment; + pipeline->depthStencilAttachmentFormat = RefreshToD3D11_SurfaceFormat[ + pipelineCreateInfo->attachmentInfo.depthStencilFormat + ]; + pipeline->stencilRef = pipelineCreateInfo->depthStencilState.backStencilState.reference; /* FIXME: Should we use front or back? */ + + pipeline->depthStencilState = D3D11_INTERNAL_FetchDepthStencilState( + renderer, + pipelineCreateInfo->depthStencilState + ); + + /* Rasterizer state */ + pipeline->primitiveTopology = RefreshToD3D11_PrimitiveType[pipelineCreateInfo->primitiveType]; + pipeline->rasterizerState = D3D11_INTERNAL_FetchRasterizerState( + renderer, + pipelineCreateInfo->rasterizerState + ); + + /* Vertex Shader + Input Layout */ + vertexShaderIndex = -1; + for (i = 0; i < vertShaderModule->numEntryPoints; i += 1) + { + if ( vertShaderModule->entryPoints[i].execution_model == SpvExecutionModelVertex && + SDL_strcmp(vertShaderModule->entryPoints[i].name, pipelineCreateInfo->vertexShaderInfo.entryPointName) == 0 ) + { + vertexShaderIndex = i; + break; + } + } + if (vertexShaderIndex == -1) + { + Refresh_LogError( + "Graphics pipeline creation failed! No entry point '%s' exists for the vertex shader!", + pipelineCreateInfo->vertexShaderInfo.entryPointName + ); + return NULL; + } + + pipeline->inputLayout = D3D11_INTERNAL_FetchInputLayout( + renderer, + pipelineCreateInfo->vertexInputState, + vertShaderModule->blobs[vertexShaderIndex] + ); + pipeline->vertexShader = (ID3D11VertexShader*) vertShaderModule->shaders[vertexShaderIndex]; + + /* Fragment Shader */ + fragmentShaderIndex = -1; + for (i = 0; i < fragShaderModule->numEntryPoints; i += 1) + { + if ( fragShaderModule->entryPoints[i].execution_model == SpvExecutionModelFragment && + SDL_strcmp(fragShaderModule->entryPoints[i].name, pipelineCreateInfo->fragmentShaderInfo.entryPointName) == 0 ) + { + fragmentShaderIndex = i; + break; + } + } + if (fragmentShaderIndex == -1) + { + Refresh_LogError( + "Graphics pipeline creation failed! No entry point '%s' exists for the fragment shader!", + pipelineCreateInfo->vertexShaderInfo.entryPointName + ); + return NULL; + } + + pipeline->fragmentShader = (ID3D11PixelShader*) fragShaderModule->shaders[fragmentShaderIndex]; + + /* FIXME: Need to create uniform buffers for the shaders */ + + return (Refresh_GraphicsPipeline*) pipeline; } static Refresh_Sampler* D3D11_CreateSampler( @@ -744,7 +1099,7 @@ static Refresh_ShaderModule* D3D11_CreateShaderModule( spvc_compiler_options compilerOptions; char *hlslSource; const char *shaderModel; - ID3DBlob *blob; + ID3DBlob **blobs; ID3DBlob *errorBlob = NULL; ID3D11DeviceChild **shaders; D3D11ShaderModule *shaderModule; @@ -804,6 +1159,11 @@ static Refresh_ShaderModule* D3D11_CreateShaderModule( SPVC_COMPILER_OPTION_HLSL_SHADER_MODEL, 50 /* shader model 5.0 */ ); + spvc_compiler_options_set_bool( + compilerOptions, + SPVC_COMPILER_OPTION_FLIP_VERTEX_Y, + SPVC_TRUE + ); spvc_compiler_install_compiler_options(compiler, compilerOptions); /* Cross compile to HLSL */ @@ -817,6 +1177,7 @@ static Refresh_ShaderModule* D3D11_CreateShaderModule( /* Allocate memory for the D3D11 shader list */ shaders = (ID3D11DeviceChild**) SDL_malloc(numEntryPoints * sizeof(ID3D11DeviceChild*)); + blobs = (ID3D10Blob**) SDL_malloc(numEntryPoints * sizeof(ID3D10Blob*)); /* Compile each HLSL entry point into a D3D shader */ for (i = 0; i < numEntryPoints; i += 1) @@ -857,7 +1218,7 @@ static Refresh_ShaderModule* D3D11_CreateShaderModule( shaderModel, 0, 0, - &blob, + &blobs[i], &errorBlob ); if (FAILED(res)) @@ -879,8 +1240,8 @@ static Refresh_ShaderModule* D3D11_CreateShaderModule( case SpvExecutionModelVertex: res = ID3D11Device_CreateVertexShader( renderer->device, - ID3D10Blob_GetBufferPointer(blob), - ID3D10Blob_GetBufferSize(blob), + ID3D10Blob_GetBufferPointer(blobs[i]), + ID3D10Blob_GetBufferSize(blobs[i]), NULL, (ID3D11VertexShader**) &shaders[i] ); @@ -889,8 +1250,8 @@ static Refresh_ShaderModule* D3D11_CreateShaderModule( case SpvExecutionModelFragment: res = ID3D11Device_CreatePixelShader( renderer->device, - ID3D10Blob_GetBufferPointer(blob), - ID3D10Blob_GetBufferSize(blob), + ID3D10Blob_GetBufferPointer(blobs[i]), + ID3D10Blob_GetBufferSize(blobs[i]), NULL, (ID3D11PixelShader**) &shaders[i] ); @@ -899,8 +1260,8 @@ static Refresh_ShaderModule* D3D11_CreateShaderModule( case SpvExecutionModelGLCompute: res = ID3D11Device_CreateComputeShader( renderer->device, - ID3D10Blob_GetBufferPointer(blob), - ID3D10Blob_GetBufferSize(blob), + ID3D10Blob_GetBufferPointer(blobs[i]), + ID3D10Blob_GetBufferSize(blobs[i]), NULL, (ID3D11ComputeShader**) &shaders[i] ); @@ -921,6 +1282,7 @@ static Refresh_ShaderModule* D3D11_CreateShaderModule( shaderModule->entryPoints = entryPoints; shaderModule->numEntryPoints = numEntryPoints; shaderModule->shaders = shaders; + shaderModule->blobs = blobs; return (Refresh_ShaderModule*) shaderModule; } @@ -936,7 +1298,45 @@ static Refresh_Buffer* D3D11_CreateBuffer( Refresh_BufferUsageFlags usageFlags, uint32_t sizeInBytes ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + ID3D11Buffer *bufferHandle; + D3D11_BUFFER_DESC bufferDesc; + uint32_t bindFlags = 0; + D3D11Buffer *result; + HRESULT res; + + if (usageFlags & REFRESH_BUFFERUSAGE_INDEX_BIT) + { + bindFlags |= D3D11_BIND_INDEX_BUFFER; + } + if (usageFlags & REFRESH_BUFFERUSAGE_VERTEX_BIT) + { + bindFlags |= D3D11_BIND_VERTEX_BUFFER; + } + if (usageFlags & REFRESH_BUFFERUSAGE_COMPUTE_BIT) + { + bindFlags |= D3D11_BIND_UNORDERED_ACCESS; + bindFlags |= D3D11_BIND_SHADER_RESOURCE; + } + + bufferDesc.BindFlags = bindFlags; + bufferDesc.ByteWidth = sizeInBytes; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; /* FIXME: Is this right...? */ + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + + res = ID3D11Device_CreateBuffer( + renderer->device, + &bufferDesc, + NULL, + &bufferHandle + ); + ERROR_CHECK_RETURN("Could not create buffer", NULL); + + result = (D3D11Buffer*) SDL_malloc(sizeof(D3D11Buffer)); + result->handle = bufferHandle; + return (Refresh_Buffer*) result; } /* Setters */ @@ -987,14 +1387,45 @@ static void D3D11_CopyTextureToBuffer( } static void D3D11_SetBufferData( - Refresh_Renderer* driverData, - Refresh_CommandBuffer* commandBuffer, - Refresh_Buffer* buffer, + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_Buffer *buffer, uint32_t offsetInBytes, - void* data, + void *data, uint32_t dataLength ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *cmdbuf = (D3D11CommandBuffer*) commandBuffer; + D3D11Buffer *buf = (D3D11Buffer*) buffer; + D3D11_MAPPED_SUBRESOURCE mappedSubresource; + HRESULT res; + + /* FIXME: How should we handle partial updates? */ + + /* Map the buffer */ + res = ID3D11DeviceContext_Map( + cmdbuf->context, + (ID3D11Resource*) buf->handle, + 0, + D3D11_MAP_WRITE_DISCARD, + 0, + &mappedSubresource + ); + ERROR_CHECK_RETURN("Could not map buffer",); + + /* Copy in the data */ + SDL_memcpy( + (uint8_t*) mappedSubresource.pData + offsetInBytes, + data, + dataLength + ); + + /* Unmap the buffer */ + ID3D11DeviceContext_Unmap( + cmdbuf->context, + (ID3D11Resource*) buf->handle, + 0 + ); } static uint32_t D3D11_PushVertexShaderUniforms( @@ -1073,7 +1504,9 @@ static void D3D11_QueueDestroyBuffer( Refresh_Renderer* driverData, Refresh_Buffer* buffer ) { - NOT_IMPLEMENTED + D3D11Buffer *d3dBuffer = (D3D11Buffer*) buffer; + ID3D11Buffer_Release(d3dBuffer->handle); + SDL_free(d3dBuffer); } static void D3D11_QueueDestroyShaderModule( @@ -1083,12 +1516,14 @@ static void D3D11_QueueDestroyShaderModule( D3D11ShaderModule *d3dShaderModule = (D3D11ShaderModule*) shaderModule; uint32_t i; - /* Release the D3D11 shader objects and free the array */ + /* Release the D3D11 shader objects and free the arrays */ for (i = 0; i < d3dShaderModule->numEntryPoints; i += 1) { ID3D11DeviceChild_Release(d3dShaderModule->shaders[i]); + ID3D10Blob_Release(d3dShaderModule->blobs[i]); } SDL_free(d3dShaderModule->shaders); + SDL_free(d3dShaderModule->blobs); /* Destroy the SPIRV-Cross context. * This should destroy the entryPoints list as well. @@ -1107,7 +1542,17 @@ static void D3D11_QueueDestroyGraphicsPipeline( Refresh_Renderer* driverData, Refresh_GraphicsPipeline* graphicsPipeline ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11GraphicsPipeline *d3dGraphicsPipeline = (D3D11GraphicsPipeline*) graphicsPipeline; + + ID3D11BlendState_Release(d3dGraphicsPipeline->colorAttachmentBlendState); + ID3D11DepthStencilState_Release(d3dGraphicsPipeline->depthStencilState); + ID3D11RasterizerState_Release(d3dGraphicsPipeline->rasterizerState); + ID3D11InputLayout_Release(d3dGraphicsPipeline->inputLayout); + + /* FIXME: Release uniform buffers, once that's written in */ + + SDL_free(d3dGraphicsPipeline); } /* Graphics State */ @@ -1201,7 +1646,31 @@ static void D3D11_BeginRenderPass( } } - /* FIXME: Set viewport and scissor state */ + /* Set default viewport and scissor state */ + /* FIXME: Check how Vulkan sets these defaults */ + viewports[0].TopLeftX = 0; + viewports[0].TopLeftY = 0; + viewports[0].Width = (float) ((D3D11Texture*) colorAttachmentInfos[0].texture)->twod.width; + viewports[0].Height = (float) ((D3D11Texture*) colorAttachmentInfos[0].texture)->twod.height; + viewports[0].MinDepth = 0; /* FIXME: Check what Vulkan does for these. */ + viewports[0].MaxDepth = 1; + + ID3D11DeviceContext_RSSetViewports( + cmdbuf->context, + 1, + viewports + ); + + scissorRects[0].left = 0; + scissorRects[0].right = (LONG) viewports[0].Width; + scissorRects[0].top = 0; + scissorRects[0].bottom = (LONG) viewports[0].Height; + + ID3D11DeviceContext_RSSetScissorRects( + cmdbuf->context, + 1, + scissorRects + ); /* FIXME: What should we do with render area? */ } @@ -1218,7 +1687,51 @@ static void D3D11_BindGraphicsPipeline( Refresh_CommandBuffer* commandBuffer, Refresh_GraphicsPipeline* graphicsPipeline ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *cmdbuf = (D3D11CommandBuffer*) commandBuffer; + D3D11GraphicsPipeline *pipeline = (D3D11GraphicsPipeline*) graphicsPipeline; + + ID3D11DeviceContext_OMSetBlendState( + cmdbuf->context, + pipeline->colorAttachmentBlendState, + pipeline->blendConstants, + 0xffffffff + ); + + ID3D11DeviceContext_OMSetDepthStencilState( + cmdbuf->context, + pipeline->depthStencilState, + pipeline->stencilRef + ); + + ID3D11DeviceContext_IASetPrimitiveTopology( + cmdbuf->context, + pipeline->primitiveTopology + ); + + ID3D11DeviceContext_IASetInputLayout( + cmdbuf->context, + pipeline->inputLayout + ); + + ID3D11DeviceContext_RSSetState( + cmdbuf->context, + pipeline->rasterizerState + ); + + ID3D11DeviceContext_VSSetShader( + cmdbuf->context, + pipeline->vertexShader, + NULL, + 0 + ); + + ID3D11DeviceContext_PSSetShader( + cmdbuf->context, + pipeline->fragmentShader, + NULL, + 0 + ); } static void D3D11_SetViewport( @@ -1245,7 +1758,32 @@ static void D3D11_BindVertexBuffers( Refresh_Buffer** pBuffers, uint64_t* pOffsets ) { - NOT_IMPLEMENTED + D3D11CommandBuffer *cmdbuf = (D3D11CommandBuffer*) commandBuffer; + ID3D11Buffer **buffers; + uint32_t *strides; + uint32_t i; + + buffers = SDL_stack_alloc(ID3D11Buffer*, bindingCount); + strides = SDL_stack_alloc(uint32_t, bindingCount); + for (i = 0; i < bindingCount; i += 1) + { + buffers[i] = ((D3D11Buffer*) pBuffers[i])->handle; + strides[i] = 20; + /* FIXME: Strides! Will probably need to get this from InputLayout somehow. */ + } + + /* FIXME: State shadowing? */ + ID3D11DeviceContext_IASetVertexBuffers( + cmdbuf->context, + firstBinding, + bindingCount, + buffers, + strides, + (const UINT*) pOffsets + ); + + SDL_stack_free(buffers); + SDL_stack_free(strides); } static void D3D11_BindIndexBuffer(